diff --git a/ImageSharp.sln b/ImageSharp.sln
index e546420ef..a584c5686 100644
--- a/ImageSharp.sln
+++ b/ImageSharp.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
-VisualStudioVersion = 15.0.26430.6
+VisualStudioVersion = 15.0.26430.14
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionItems", "{C317F1B1-D75E-4C6D-83EB-80367343E0D7}"
ProjectSection(SolutionItems) = preProject
@@ -49,6 +49,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{7CC6
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AvatarWithRoundedCorner", "samples\AvatarWithRoundedCorner\AvatarWithRoundedCorner.csproj", "{844FC582-4E78-4371-847D-EFD4D1103578}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChangeDefaultEncoderOptions", "samples\ChangeDefaultEncoderOptions\ChangeDefaultEncoderOptions.csproj", "{07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -143,6 +145,18 @@ Global
{844FC582-4E78-4371-847D-EFD4D1103578}.Release|x64.Build.0 = Release|Any CPU
{844FC582-4E78-4371-847D-EFD4D1103578}.Release|x86.ActiveCfg = Release|Any CPU
{844FC582-4E78-4371-847D-EFD4D1103578}.Release|x86.Build.0 = Release|Any CPU
+ {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Debug|x64.Build.0 = Debug|Any CPU
+ {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Debug|x86.Build.0 = Debug|Any CPU
+ {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Release|x64.ActiveCfg = Release|Any CPU
+ {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Release|x64.Build.0 = Release|Any CPU
+ {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Release|x86.ActiveCfg = Release|Any CPU
+ {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -156,5 +170,6 @@ Global
{2BF743D8-2A06-412D-96D7-F448F00C5EA5} = {56801022-D71A-4FBE-BC5B-CBA08E2284EC}
{96188137-5FA6-4924-AB6E-4EFF79C6E0BB} = {56801022-D71A-4FBE-BC5B-CBA08E2284EC}
{844FC582-4E78-4371-847D-EFD4D1103578} = {7CC6D57E-B916-43B8-B315-A0BB92F260A2}
+ {07EE511D-4BAB-4323-BAFC-3AF2BF9366F0} = {7CC6D57E-B916-43B8-B315-A0BB92F260A2}
EndGlobalSection
EndGlobal
diff --git a/samples/ChangeDefaultEncoderOptions/ChangeDefaultEncoderOptions.csproj b/samples/ChangeDefaultEncoderOptions/ChangeDefaultEncoderOptions.csproj
new file mode 100644
index 000000000..5797be0f5
--- /dev/null
+++ b/samples/ChangeDefaultEncoderOptions/ChangeDefaultEncoderOptions.csproj
@@ -0,0 +1,12 @@
+
+
+
+ Exe
+ netcoreapp1.1
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/ChangeDefaultEncoderOptions/Program.cs b/samples/ChangeDefaultEncoderOptions/Program.cs
new file mode 100644
index 000000000..dab8d445c
--- /dev/null
+++ b/samples/ChangeDefaultEncoderOptions/Program.cs
@@ -0,0 +1,20 @@
+using System;
+using ImageSharp;
+using ImageSharp.Formats;
+
+namespace ChangeDefaultEncoderOptions
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ // lets switch out the default encoder for jpeg to one
+ // that saves at 90 quality and ignores the matadata
+ Configuration.Default.SetEncoder(ImageFormats.Jpeg, new ImageSharp.Formats.JpegEncoder()
+ {
+ Quality = 90,
+ IgnoreMetadata = true
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Common/Exceptions/ImageFormatException.cs b/src/ImageSharp/Common/Exceptions/ImageFormatException.cs
index 70491ba22..32a085435 100644
--- a/src/ImageSharp/Common/Exceptions/ImageFormatException.cs
+++ b/src/ImageSharp/Common/Exceptions/ImageFormatException.cs
@@ -11,7 +11,7 @@ namespace ImageSharp
/// The exception that is thrown when the library tries to load
/// an image, which has an invalid format.
///
- public class ImageFormatException : Exception
+ public sealed class ImageFormatException : Exception
{
///
/// Initializes a new instance of the class.
diff --git a/src/ImageSharp/Common/Exceptions/ImageProcessingException.cs b/src/ImageSharp/Common/Exceptions/ImageProcessingException.cs
index a59be9ca8..ef84a1e39 100644
--- a/src/ImageSharp/Common/Exceptions/ImageProcessingException.cs
+++ b/src/ImageSharp/Common/Exceptions/ImageProcessingException.cs
@@ -10,7 +10,7 @@ namespace ImageSharp
///
/// The exception that is thrown when an error occurs when applying a process to an image.
///
- public class ImageProcessingException : Exception
+ public sealed class ImageProcessingException : Exception
{
///
/// Initializes a new instance of the class.
diff --git a/src/ImageSharp/Configuration.cs b/src/ImageSharp/Configuration.cs
index fa983d355..226d45132 100644
--- a/src/ImageSharp/Configuration.cs
+++ b/src/ImageSharp/Configuration.cs
@@ -6,8 +6,8 @@
namespace ImageSharp
{
using System;
+ using System.Collections.Concurrent;
using System.Collections.Generic;
- using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
@@ -17,22 +17,32 @@ namespace ImageSharp
///
/// Provides initialization code which allows extending the library.
///
- public class Configuration
+ public sealed class Configuration
{
///
/// A lazily initialized configuration default instance.
///
- private static readonly Lazy Lazy = new Lazy(() => CreateDefaultInstance());
+ private static readonly Lazy Lazy = new Lazy(CreateDefaultInstance);
///
- /// An object that can be used to synchronize access to the .
+ /// The list of supported keyed to mime types.
///
- private readonly object syncRoot = new object();
+ private readonly ConcurrentDictionary mimeTypeEncoders = new ConcurrentDictionary();
///
- /// The list of supported .
+ /// The list of supported keyed to mime types.
///
- private readonly List imageFormatsList = new List();
+ private readonly ConcurrentDictionary mimeTypeDecoders = new ConcurrentDictionary();
+
+ ///
+ /// The list of supported s.
+ ///
+ private readonly List imageFormatDetectors = new List();
+
+ ///
+ /// The list of supported s.
+ ///
+ private readonly HashSet imageFormats = new HashSet();
///
/// Initializes a new instance of the class.
@@ -44,12 +54,15 @@ namespace ImageSharp
///
/// Initializes a new instance of the class.
///
- /// The inital set of image formats.
- public Configuration(params IImageFormat[] providers)
+ /// A collection of configuration modules to register
+ public Configuration(params IConfigurationModule[] configurationModules)
{
- foreach (IImageFormat p in providers)
+ if (configurationModules != null)
{
- this.AddImageFormat(p);
+ foreach (IConfigurationModule p in configurationModules)
+ {
+ p.Configure(this);
+ }
}
}
@@ -58,21 +71,36 @@ namespace ImageSharp
///
public static Configuration Default { get; } = Lazy.Value;
- ///
- /// Gets the collection of supported
- ///
- public IReadOnlyCollection ImageFormats => new ReadOnlyCollection(this.imageFormatsList);
-
///
/// Gets the global parallel options for processing tasks in parallel.
///
public ParallelOptions ParallelOptions { get; } = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount };
///
- /// Gets the maximum header size of all formats.
+ /// Gets the maximum header size of all the formats.
///
internal int MaxHeaderSize { get; private set; }
+ ///
+ /// Gets the currently registered s.
+ ///
+ internal IEnumerable FormatDetectors => this.imageFormatDetectors;
+
+ ///
+ /// Gets the currently registered s.
+ ///
+ internal IEnumerable> ImageDecoders => this.mimeTypeDecoders;
+
+ ///
+ /// Gets the currently registered s.
+ ///
+ internal IEnumerable> ImageEncoders => this.mimeTypeEncoders;
+
+ ///
+ /// Gets the currently registered s.
+ ///
+ internal IEnumerable ImageFormats => this.imageFormats;
+
#if !NETSTANDARD1_1
///
/// Gets or sets the fielsystem helper for accessing the local file system.
@@ -81,126 +109,147 @@ namespace ImageSharp
#endif
///
- /// Adds a new to the collection of supported image formats.
+ /// Registers a new format provider.
///
- /// The new format to add.
+ /// The configuration provider to call configure on.
+ public void Configure(IConfigurationModule configuration)
+ {
+ Guard.NotNull(configuration, nameof(configuration));
+ configuration.Configure(this);
+ }
+
+ ///
+ /// Registers a new format provider.
+ ///
+ /// The format to register as a well know format.
public void AddImageFormat(IImageFormat format)
{
Guard.NotNull(format, nameof(format));
- Guard.NotNull(format.Encoder, nameof(format), "The encoder should not be null.");
- Guard.NotNull(format.Decoder, nameof(format), "The decoder should not be null.");
- Guard.NotNullOrEmpty(format.MimeType, nameof(format), "The mime type should not be null or empty.");
- Guard.NotNullOrEmpty(format.Extension, nameof(format), "The extension should not be null or empty.");
- Guard.NotNullOrEmpty(format.SupportedExtensions, nameof(format), "The supported extensions not be null or empty.");
+ Guard.NotNull(format.MimeTypes, nameof(format.MimeTypes));
+ Guard.NotNull(format.FileExtensions, nameof(format.FileExtensions));
+ this.imageFormats.Add(format);
+ }
- this.AddImageFormatLocked(format);
+ ///
+ /// For the specified file extensions type find the e .
+ ///
+ /// The extension to discover
+ /// The if found otherwise null
+ public IImageFormat FindFormatByFileExtensions(string extension)
+ {
+ return this.imageFormats.FirstOrDefault(x => x.FileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase));
}
///
- /// Creates the default instance, with Png, Jpeg, Gif and Bmp preregisterd (if they have been referenced)
+ /// For the specified mime type find the .
///
- /// The default configuration of
- internal static Configuration CreateDefaultInstance()
+ /// The mime-type to discover
+ /// The if found otherwise null
+ public IImageFormat FindFormatByMimeType(string mimeType)
{
- Configuration config = new Configuration();
-
- // lets try auto loading the known image formats
- config.AddImageFormat(new Formats.PngFormat());
- config.AddImageFormat(new Formats.JpegFormat());
- config.AddImageFormat(new Formats.GifFormat());
- config.AddImageFormat(new Formats.BmpFormat());
- return config;
+ return this.imageFormats.FirstOrDefault(x => x.MimeTypes.Contains(mimeType, StringComparer.OrdinalIgnoreCase));
}
///
- /// Tries the add image format.
+ /// Sets a specific image encoder as the encoder for a specific image format.
///
- /// Name of the type.
- /// True if type discoverd and is a valid
- internal bool TryAddImageFormat(string typeName)
+ /// The image format to register the encoder for.
+ /// The encoder to use,
+ public void SetEncoder(IImageFormat imageFormat, IImageEncoder encoder)
{
- Type type = Type.GetType(typeName, false);
- if (type != null)
- {
- IImageFormat format = Activator.CreateInstance(type) as IImageFormat;
- if (format != null
- && format.Encoder != null
- && format.Decoder != null
- && !string.IsNullOrEmpty(format.MimeType)
- && format.SupportedExtensions?.Any() == true)
- {
- // we can use the locked version as we have already validated in the if.
- this.AddImageFormatLocked(format);
- return true;
- }
- }
+ Guard.NotNull(imageFormat, nameof(imageFormat));
+ Guard.NotNull(encoder, nameof(encoder));
+ this.AddImageFormat(imageFormat);
+ this.mimeTypeEncoders.AddOrUpdate(imageFormat, encoder, (s, e) => encoder);
+ }
- return false;
+ ///
+ /// Sets a specific image decoder as the decoder for a specific image format.
+ ///
+ /// The image format to register the encoder for.
+ /// The decoder to use,
+ public void SetDecoder(IImageFormat imageFormat, IImageDecoder decoder)
+ {
+ Guard.NotNull(imageFormat, nameof(imageFormat));
+ Guard.NotNull(decoder, nameof(decoder));
+ this.AddImageFormat(imageFormat);
+ this.mimeTypeDecoders.AddOrUpdate(imageFormat, decoder, (s, e) => decoder);
}
///
- /// Adds image format. The class is locked to make it thread safe.
+ /// Removes all the registered image format detectors.
///
- /// The image format.
- private void AddImageFormatLocked(IImageFormat format)
+ public void ClearImageFormatDetectors()
{
- lock (this.syncRoot)
- {
- if (this.GuardDuplicate(format))
- {
- this.imageFormatsList.Add(format);
+ this.imageFormatDetectors.Clear();
+ }
- this.SetMaxHeaderSize();
- }
- }
+ ///
+ /// Adds a new detector for detecting mime types.
+ ///
+ /// The detector to add
+ public void AddImageFormatDetector(IImageFormatDetector detector)
+ {
+ Guard.NotNull(detector, nameof(detector));
+ this.imageFormatDetectors.Add(detector);
+ this.SetMaxHeaderSize();
}
///
- /// Checks to ensure duplicate image formats are not added.
+ /// Creates the default instance with the following s preregistered:
+ ///
+ ///
+ ///
+ ///
///
- /// The image format.
- /// Thrown if a duplicate is added.
- ///
- /// The .
- ///
- private bool GuardDuplicate(IImageFormat format)
+ /// The default configuration of
+ internal static Configuration CreateDefaultInstance()
{
- if (!format.SupportedExtensions.Contains(format.Extension, StringComparer.OrdinalIgnoreCase))
- {
- throw new ArgumentException("The supported extensions should contain the default extension.", nameof(format));
- }
+ return new Configuration(
+ new PngConfigurationModule(),
+ new JpegConfigurationModule(),
+ new GifConfigurationModule(),
+ new BmpConfigurationModule());
+ }
- // ReSharper disable once ConvertClosureToMethodGroup
- // Prevents method group allocation
- if (format.SupportedExtensions.Any(e => string.IsNullOrWhiteSpace(e)))
+ ///
+ /// For the specified mime type find the decoder.
+ ///
+ /// The format to discover
+ /// The if found otherwise null
+ internal IImageDecoder FindDecoder(IImageFormat format)
+ {
+ Guard.NotNull(format, nameof(format));
+ if (this.mimeTypeDecoders.TryGetValue(format, out IImageDecoder decoder))
{
- throw new ArgumentException("The supported extensions should not contain empty values.", nameof(format));
+ return decoder;
}
- // If there is already a format with the same extension or a format that supports that
- // extension return false.
- foreach (IImageFormat imageFormat in this.imageFormatsList)
- {
- if (imageFormat.Extension.Equals(format.Extension, StringComparison.OrdinalIgnoreCase))
- {
- return false;
- }
+ return null;
+ }
- if (imageFormat.SupportedExtensions.Intersect(format.SupportedExtensions, StringComparer.OrdinalIgnoreCase).Any())
- {
- return false;
- }
+ ///
+ /// For the specified mime type find the encoder.
+ ///
+ /// The format to discover
+ /// The if found otherwise null
+ internal IImageEncoder FindEncoder(IImageFormat format)
+ {
+ Guard.NotNull(format, nameof(format));
+ if (this.mimeTypeEncoders.TryGetValue(format, out IImageEncoder encoder))
+ {
+ return encoder;
}
- return true;
+ return null;
}
///
- /// Sets max header size.
+ /// Sets the max header size.
///
private void SetMaxHeaderSize()
{
- this.MaxHeaderSize = this.imageFormatsList.Max(x => x.HeaderSize);
+ this.MaxHeaderSize = this.imageFormatDetectors.Max(x => x.HeaderSize);
}
}
}
diff --git a/src/ImageSharp/Formats/Bmp/BmpConfigurationModule.cs b/src/ImageSharp/Formats/Bmp/BmpConfigurationModule.cs
new file mode 100644
index 000000000..f70ff1a56
--- /dev/null
+++ b/src/ImageSharp/Formats/Bmp/BmpConfigurationModule.cs
@@ -0,0 +1,21 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Formats
+{
+ ///
+ /// Registers the image encoders, decoders and mime type detectors for the bmp format.
+ ///
+ public sealed class BmpConfigurationModule : IConfigurationModule
+ {
+ ///
+ public void Configure(Configuration config)
+ {
+ config.SetEncoder(ImageFormats.Bitmap, new BmpEncoder());
+ config.SetDecoder(ImageFormats.Bitmap, new BmpDecoder());
+ config.AddImageFormatDetector(new BmpImageFormatDetector());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Bmp/BmpConstants.cs b/src/ImageSharp/Formats/Bmp/BmpConstants.cs
new file mode 100644
index 000000000..d394b61f6
--- /dev/null
+++ b/src/ImageSharp/Formats/Bmp/BmpConstants.cs
@@ -0,0 +1,25 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Formats
+{
+ using System.Collections.Generic;
+
+ ///
+ /// Defines constants relating to BMPs
+ ///
+ internal static class BmpConstants
+ {
+ ///
+ /// The list of mimetypes that equate to a bmp.
+ ///
+ public static readonly IEnumerable MimeTypes = new[] { "image/bmp", "image/x-windows-bmp" };
+
+ ///
+ /// The list of file extensions that equate to a bmp.
+ ///
+ public static readonly IEnumerable FileExtensions = new[] { "bm", "bmp", "dip" };
+ }
+}
diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoder.cs b/src/ImageSharp/Formats/Bmp/BmpDecoder.cs
index 9090e9a8c..5baf1b1a5 100644
--- a/src/ImageSharp/Formats/Bmp/BmpDecoder.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpDecoder.cs
@@ -6,6 +6,7 @@
namespace ImageSharp.Formats
{
using System;
+ using System.Collections.Generic;
using System.IO;
using ImageSharp.PixelFormats;
@@ -25,16 +26,16 @@ namespace ImageSharp.Formats
/// Formats will be supported in a later releases. We advise always
/// to use only 24 Bit Windows bitmaps.
///
- public class BmpDecoder : IImageDecoder
+ public sealed class BmpDecoder : IImageDecoder, IBmpDecoderOptions
{
///
- public Image Decode(Configuration configuration, Stream stream, IDecoderOptions options)
+ public Image Decode(Configuration configuration, Stream stream)
where TPixel : struct, IPixel
{
Guard.NotNull(stream, "stream");
- return new BmpDecoderCore(configuration).Decode(stream);
+ return new BmpDecoderCore(configuration, this).Decode(stream);
}
}
}
diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
index 997a77d6c..817d00f7e 100644
--- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
@@ -52,7 +52,8 @@ namespace ImageSharp.Formats
/// Initializes a new instance of the class.
///
/// The configuration.
- public BmpDecoderCore(Configuration configuration)
+ /// The options
+ public BmpDecoderCore(Configuration configuration, IBmpDecoderOptions options)
{
this.configuration = configuration;
}
diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoder.cs b/src/ImageSharp/Formats/Bmp/BmpEncoder.cs
index dc2bc0e97..dfba0b41c 100644
--- a/src/ImageSharp/Formats/Bmp/BmpEncoder.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpEncoder.cs
@@ -6,6 +6,7 @@
namespace ImageSharp.Formats
{
using System;
+ using System.Collections.Generic;
using System.IO;
using ImageSharp.PixelFormats;
@@ -14,28 +15,18 @@ namespace ImageSharp.Formats
/// Image encoder for writing an image to a stream as a Windows bitmap.
///
/// The encoder can currently only write 24-bit rgb images to streams.
- public class BmpEncoder : IImageEncoder
+ public sealed class BmpEncoder : IImageEncoder, IBmpEncoderOptions
{
- ///
- public void Encode(Image image, Stream stream, IEncoderOptions options)
- where TPixel : struct, IPixel
- {
- IBmpEncoderOptions bmpOptions = BmpEncoderOptions.Create(options);
-
- this.Encode(image, stream, bmpOptions);
- }
-
///
- /// Encodes the image to the specified stream from the .
+ /// Gets or sets the number of bits per pixel.
///
- /// The pixel format.
- /// The to encode from.
- /// The to encode the image data to.
- /// The options for the encoder.
- public void Encode(Image image, Stream stream, IBmpEncoderOptions options)
+ public BmpBitsPerPixel BitsPerPixel { get; set; } = BmpBitsPerPixel.Pixel24;
+
+ ///
+ public void Encode(Image image, Stream stream)
where TPixel : struct, IPixel
{
- BmpEncoderCore encoder = new BmpEncoderCore(options);
+ var encoder = new BmpEncoderCore(this);
encoder.Encode(image, stream);
}
}
diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
index 617edde8e..e41c29501 100644
--- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
@@ -18,22 +18,22 @@ namespace ImageSharp.Formats
internal sealed class BmpEncoderCore
{
///
- /// The options for the encoder.
+ /// The amount to pad each row by.
///
- private readonly IBmpEncoderOptions options;
+ private int padding;
///
- /// The amount to pad each row by.
+ /// Gets or sets the number of bits per pixel.
///
- private int padding;
+ private BmpBitsPerPixel bitsPerPixel;
///
/// Initializes a new instance of the class.
///
- /// The options for the encoder.
+ /// The encoder options
public BmpEncoderCore(IBmpEncoderOptions options)
{
- this.options = options ?? new BmpEncoderOptions();
+ this.bitsPerPixel = options.BitsPerPixel;
}
///
@@ -49,9 +49,9 @@ namespace ImageSharp.Formats
Guard.NotNull(stream, nameof(stream));
// Cast to int will get the bytes per pixel
- short bpp = (short)(8 * (int)this.options.BitsPerPixel);
+ short bpp = (short)(8 * (int)this.bitsPerPixel);
int bytesPerLine = 4 * (((image.Width * bpp) + 31) / 32);
- this.padding = bytesPerLine - (image.Width * (int)this.options.BitsPerPixel);
+ this.padding = bytesPerLine - (image.Width * (int)this.bitsPerPixel);
// Do not use IDisposable pattern here as we want to preserve the stream.
EndianBinaryWriter writer = new EndianBinaryWriter(Endianness.LittleEndian, stream);
@@ -136,7 +136,7 @@ namespace ImageSharp.Formats
{
using (PixelAccessor pixels = image.Lock())
{
- switch (this.options.BitsPerPixel)
+ switch (this.bitsPerPixel)
{
case BmpBitsPerPixel.Pixel32:
this.Write32Bit(writer, pixels);
diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderOptions.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderOptions.cs
deleted file mode 100644
index a0f9ff8e0..000000000
--- a/src/ImageSharp/Formats/Bmp/BmpEncoderOptions.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-//
-// Copyright (c) James Jackson-South and contributors.
-// Licensed under the Apache License, Version 2.0.
-//
-
-namespace ImageSharp.Formats
-{
- ///
- /// Encapsulates the options for the .
- ///
- public sealed class BmpEncoderOptions : EncoderOptions, IBmpEncoderOptions
- {
- ///
- /// Initializes a new instance of the class.
- ///
- public BmpEncoderOptions()
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The options for the encoder.
- private BmpEncoderOptions(IEncoderOptions options)
- : base(options)
- {
- }
-
- ///
- /// Gets or sets the number of bits per pixel.
- ///
- public BmpBitsPerPixel BitsPerPixel { get; set; } = BmpBitsPerPixel.Pixel24;
-
- ///
- /// Converts the options to a instance with a cast
- /// or by creating a new instance with the specfied options.
- ///
- /// The options for the encoder.
- /// The options for the .
- internal static IBmpEncoderOptions Create(IEncoderOptions options)
- {
- return options as IBmpEncoderOptions ?? new BmpEncoderOptions(options);
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Bmp/BmpFileHeader.cs b/src/ImageSharp/Formats/Bmp/BmpFileHeader.cs
index 4be602f4b..f9b20a48f 100644
--- a/src/ImageSharp/Formats/Bmp/BmpFileHeader.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpFileHeader.cs
@@ -15,7 +15,7 @@ namespace ImageSharp.Formats
/// All of the other integer values are stored in little-endian format
/// (i.e. least-significant byte first).
///
- internal class BmpFileHeader
+ internal sealed class BmpFileHeader
{
///
/// Defines of the data structure in the bitmap file.
diff --git a/src/ImageSharp/Formats/Bmp/BmpFormat.cs b/src/ImageSharp/Formats/Bmp/BmpFormat.cs
index bf73d3162..fb65f34d7 100644
--- a/src/ImageSharp/Formats/Bmp/BmpFormat.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpFormat.cs
@@ -1,4 +1,4 @@
-//
+//
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
//
@@ -8,34 +8,20 @@ namespace ImageSharp.Formats
using System.Collections.Generic;
///
- /// Encapsulates the means to encode and decode bitmap images.
+ /// Registers the image encoders, decoders and mime type detectors for the jpeg format.
///
- public class BmpFormat : IImageFormat
+ internal sealed class BmpFormat : IImageFormat
{
///
- public string MimeType => "image/bmp";
+ public string Name => "BMP";
///
- public string Extension => "bmp";
+ public string DefaultMimeType => "image/bmp";
///
- public IEnumerable SupportedExtensions => new string[] { "bmp", "dip" };
+ public IEnumerable MimeTypes => BmpConstants.MimeTypes;
///
- public IImageDecoder Decoder => new BmpDecoder();
-
- ///
- public IImageEncoder Encoder => new BmpEncoder();
-
- ///
- public int HeaderSize => 2;
-
- ///
- public bool IsSupportedFileFormat(byte[] header)
- {
- return header.Length >= this.HeaderSize &&
- header[0] == 0x42 && // B
- header[1] == 0x4D; // M
- }
+ public IEnumerable FileExtensions => BmpConstants.FileExtensions;
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs b/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs
new file mode 100644
index 000000000..697ee0f98
--- /dev/null
+++ b/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs
@@ -0,0 +1,37 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Formats
+{
+ using System;
+
+ ///
+ /// Detects bmp file headers
+ ///
+ public sealed class BmpImageFormatDetector : IImageFormatDetector
+ {
+ ///
+ public int HeaderSize => 2;
+
+ ///
+ public IImageFormat DetectFormat(ReadOnlySpan header)
+ {
+ if (this.IsSupportedFileFormat(header))
+ {
+ return ImageFormats.Bitmap;
+ }
+
+ return null;
+ }
+
+ private bool IsSupportedFileFormat(ReadOnlySpan header)
+ {
+ // TODO: This should be in constants
+ return header.Length >= this.HeaderSize &&
+ header[0] == 0x42 && // B
+ header[1] == 0x4D; // M
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs b/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs
index e652cb504..dc6a489d3 100644
--- a/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs
@@ -10,7 +10,7 @@ namespace ImageSharp.Formats
/// the screen.
///
///
- internal class BmpInfoHeader
+ internal sealed class BmpInfoHeader
{
///
/// Defines of the data structure in the bitmap file.
diff --git a/src/ImageSharp/Formats/Bmp/IBmpDecoderOptions.cs b/src/ImageSharp/Formats/Bmp/IBmpDecoderOptions.cs
new file mode 100644
index 000000000..9285b9cf7
--- /dev/null
+++ b/src/ImageSharp/Formats/Bmp/IBmpDecoderOptions.cs
@@ -0,0 +1,21 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Formats
+{
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+
+ using ImageSharp.PixelFormats;
+
+ ///
+ /// Image decoder options for decoding Windows bitmap streams.
+ ///
+ internal interface IBmpDecoderOptions
+ {
+ // added this for consistancy so we can add stuff as required, no options currently availible
+ }
+}
diff --git a/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs b/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs
index 6cf37cbae..dd17043fa 100644
--- a/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs
+++ b/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs
@@ -1,14 +1,21 @@
-//
+//
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
//
namespace ImageSharp.Formats
{
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+
+ using ImageSharp.PixelFormats;
+
///
- /// Encapsulates the options for the .
+ /// Configuration options for use during bmp encoding
///
- public interface IBmpEncoderOptions : IEncoderOptions
+ /// The encoder can currently only write 24-bit rgb images to streams.
+ internal interface IBmpEncoderOptions
{
///
/// Gets the number of bits per pixel.
diff --git a/src/ImageSharp/Formats/DecoderOptions.cs b/src/ImageSharp/Formats/DecoderOptions.cs
deleted file mode 100644
index 5257b07b3..000000000
--- a/src/ImageSharp/Formats/DecoderOptions.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-//
-// Copyright (c) James Jackson-South and contributors.
-// Licensed under the Apache License, Version 2.0.
-//
-
-namespace ImageSharp
-{
- ///
- /// Encapsulates the shared decoder options.
- ///
- public class DecoderOptions : IDecoderOptions
- {
- ///
- /// Initializes a new instance of the class.
- ///
- public DecoderOptions()
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The decoder options
- protected DecoderOptions(IDecoderOptions options)
- {
- if (options != null)
- {
- this.IgnoreMetadata = options.IgnoreMetadata;
- }
- }
-
- ///
- /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
- ///
- public bool IgnoreMetadata { get; set; } = false;
- }
-}
diff --git a/src/ImageSharp/Formats/EncoderOptions.cs b/src/ImageSharp/Formats/EncoderOptions.cs
deleted file mode 100644
index 27a7e9781..000000000
--- a/src/ImageSharp/Formats/EncoderOptions.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-//
-// Copyright (c) James Jackson-South and contributors.
-// Licensed under the Apache License, Version 2.0.
-//
-
-namespace ImageSharp
-{
- ///
- /// Encapsulates the shared encoder options.
- ///
- public class EncoderOptions : IEncoderOptions
- {
- ///
- /// Initializes a new instance of the class.
- ///
- public EncoderOptions()
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The encoder options
- protected EncoderOptions(IEncoderOptions options)
- {
- if (options != null)
- {
- this.IgnoreMetadata = options.IgnoreMetadata;
- }
- }
-
- ///
- /// Gets or sets a value indicating whether the metadata should be ignored when the image is being encoded.
- ///
- public bool IgnoreMetadata { get; set; } = false;
- }
-}
diff --git a/src/ImageSharp/Formats/Gif/GifConfigurationModule.cs b/src/ImageSharp/Formats/Gif/GifConfigurationModule.cs
new file mode 100644
index 000000000..ee134d66c
--- /dev/null
+++ b/src/ImageSharp/Formats/Gif/GifConfigurationModule.cs
@@ -0,0 +1,22 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Formats
+{
+ ///
+ /// Registers the image encoders, decoders and mime type detectors for the gif format.
+ ///
+ public sealed class GifConfigurationModule : IConfigurationModule
+ {
+ ///
+ public void Configure(Configuration config)
+ {
+ config.SetEncoder(ImageFormats.Gif, new GifEncoder());
+ config.SetDecoder(ImageFormats.Gif, new GifDecoder());
+
+ config.AddImageFormatDetector(new GifImageFormatDetector());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Gif/GifConstants.cs b/src/ImageSharp/Formats/Gif/GifConstants.cs
index 4af291c2b..9bec6c48f 100644
--- a/src/ImageSharp/Formats/Gif/GifConstants.cs
+++ b/src/ImageSharp/Formats/Gif/GifConstants.cs
@@ -5,6 +5,7 @@
namespace ImageSharp.Formats
{
+ using System.Collections.Generic;
using System.Text;
///
@@ -90,6 +91,16 @@ namespace ImageSharp.Formats
///
/// Gets the default encoding to use when reading comments.
///
- public static Encoding DefaultEncoding { get; } = Encoding.GetEncoding("ASCII");
+ public static readonly Encoding DefaultEncoding = Encoding.GetEncoding("ASCII");
+
+ ///
+ /// The list of mimetypes that equate to a gif.
+ ///
+ public static readonly IEnumerable MimeTypes = new[] { "image/gif" };
+
+ ///
+ /// The list of file extensions that equate to a gif.
+ ///
+ public static readonly IEnumerable FileExtensions = new[] { "gif" };
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Gif/GifDecoder.cs b/src/ImageSharp/Formats/Gif/GifDecoder.cs
index 88aaccf6a..927289094 100644
--- a/src/ImageSharp/Formats/Gif/GifDecoder.cs
+++ b/src/ImageSharp/Formats/Gif/GifDecoder.cs
@@ -6,37 +6,32 @@
namespace ImageSharp.Formats
{
using System;
+ using System.Collections.Generic;
using System.IO;
-
+ using System.Text;
using ImageSharp.PixelFormats;
///
/// Decoder for generating an image out of a gif encoded stream.
///
- public class GifDecoder : IImageDecoder
+ public sealed class GifDecoder : IImageDecoder, IGifDecoderOptions
{
- ///
- public Image Decode(Configuration configuration, Stream stream, IDecoderOptions options)
-
- where TPixel : struct, IPixel
- {
- IGifDecoderOptions gifOptions = GifDecoderOptions.Create(options);
-
- return this.Decode(configuration, stream, gifOptions);
- }
+ ///
+ /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
+ ///
+ public bool IgnoreMetadata { get; set; } = false;
///
- /// Decodes the image from the specified stream to the .
+ /// Gets or sets the encoding that should be used when reading comments.
///
- /// The pixel format.
- /// The configuration.
- /// The containing image data.
- /// The options for the decoder.
- /// The image thats been decoded.
- public Image Decode(Configuration configuration, Stream stream, IGifDecoderOptions options)
+ public Encoding TextEncoding { get; set; } = GifConstants.DefaultEncoding;
+
+ ///
+ public Image Decode(Configuration configuration, Stream stream)
where TPixel : struct, IPixel
{
- return new GifDecoderCore(options, configuration).Decode(stream);
+ var decoder = new GifDecoderCore(configuration, this);
+ return decoder.Decode(stream);
}
}
}
diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
index ef0331c0d..bb230beac 100644
--- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
@@ -18,7 +18,7 @@ namespace ImageSharp.Formats
/// Performs the gif decoding operation.
///
/// The pixel format.
- internal class GifDecoderCore
+ internal sealed class GifDecoderCore
where TPixel : struct, IPixel
{
///
@@ -26,11 +26,6 @@ namespace ImageSharp.Formats
///
private readonly byte[] buffer = new byte[16];
- ///
- /// The decoder options.
- ///
- private readonly IGifDecoderOptions options;
-
///
/// The global configuration.
///
@@ -84,14 +79,25 @@ namespace ImageSharp.Formats
///
/// Initializes a new instance of the class.
///
- /// The decoder options.
/// The configuration.
- public GifDecoderCore(IGifDecoderOptions options, Configuration configuration)
+ /// The decoder options.
+ public GifDecoderCore(Configuration configuration, IGifDecoderOptions options)
{
- this.options = options ?? new GifDecoderOptions();
+ this.TextEncoding = options.TextEncoding ?? GifConstants.DefaultEncoding;
+ this.IgnoreMetadata = options.IgnoreMetadata;
this.configuration = configuration ?? Configuration.Default;
}
+ ///
+ /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
+ ///
+ public bool IgnoreMetadata { get; internal set; }
+
+ ///
+ /// Gets the text encoding
+ ///
+ public Encoding TextEncoding { get; private set; }
+
///
/// Decodes the stream to the image.
///
@@ -269,7 +275,7 @@ namespace ImageSharp.Formats
throw new ImageFormatException($"Gif comment length '{length}' exceeds max '{GifConstants.MaxCommentLength}'");
}
- if (this.options.IgnoreMetadata)
+ if (this.IgnoreMetadata)
{
this.currentStream.Seek(length, SeekOrigin.Current);
continue;
@@ -280,7 +286,7 @@ namespace ImageSharp.Formats
try
{
this.currentStream.Read(commentsBuffer, 0, length);
- string comments = this.options.TextEncoding.GetString(commentsBuffer, 0, length);
+ string comments = this.TextEncoding.GetString(commentsBuffer, 0, length);
this.metaData.Properties.Add(new ImageProperty(GifConstants.Comments, comments));
}
finally
@@ -364,8 +370,6 @@ namespace ImageSharp.Formats
if (this.previousFrame == null)
{
- this.metaData.Quality = colorTableLength / 3;
-
// This initializes the image to become fully transparent because the alpha channel is zero.
this.image = new Image(this.configuration, imageWidth, imageHeight, this.metaData);
diff --git a/src/ImageSharp/Formats/Gif/GifDecoderOptions.cs b/src/ImageSharp/Formats/Gif/GifDecoderOptions.cs
deleted file mode 100644
index bc7709f75..000000000
--- a/src/ImageSharp/Formats/Gif/GifDecoderOptions.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-//
-// Copyright (c) James Jackson-South and contributors.
-// Licensed under the Apache License, Version 2.0.
-//
-
-namespace ImageSharp.Formats
-{
- using System.Text;
-
- ///
- /// Encapsulates the options for the .
- ///
- public sealed class GifDecoderOptions : DecoderOptions, IGifDecoderOptions
- {
- ///
- /// Initializes a new instance of the class.
- ///
- public GifDecoderOptions()
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The options for the decoder.
- private GifDecoderOptions(IDecoderOptions options)
- : base(options)
- {
- }
-
- ///
- /// Gets or sets the encoding that should be used when reading comments.
- ///
- public Encoding TextEncoding { get; set; } = GifConstants.DefaultEncoding;
-
- ///
- /// Converts the options to a instance with a cast
- /// or by creating a new instance with the specfied options.
- ///
- /// The options for the decoder.
- /// The options for the .
- internal static IGifDecoderOptions Create(IDecoderOptions options)
- {
- return options as IGifDecoderOptions ?? new GifDecoderOptions(options);
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Gif/GifEncoder.cs b/src/ImageSharp/Formats/Gif/GifEncoder.cs
index b5cadd834..b48db5635 100644
--- a/src/ImageSharp/Formats/Gif/GifEncoder.cs
+++ b/src/ImageSharp/Formats/Gif/GifEncoder.cs
@@ -6,35 +6,47 @@
namespace ImageSharp.Formats
{
using System;
+ using System.Collections.Generic;
using System.IO;
-
+ using System.Text;
using ImageSharp.PixelFormats;
+ using ImageSharp.Quantizers;
///
/// Image encoder for writing image data to a stream in gif format.
///
- public class GifEncoder : IImageEncoder
+ public sealed class GifEncoder : IImageEncoder, IGifEncoderOptions
{
- ///
- public void Encode(Image image, Stream stream, IEncoderOptions options)
- where TPixel : struct, IPixel
- {
- IGifEncoderOptions gifOptions = GifEncoderOptions.Create(options);
+ ///
+ /// Gets or sets a value indicating whether the metadata should be ignored when the image is being encoded.
+ ///
+ public bool IgnoreMetadata { get; set; } = false;
- this.Encode(image, stream, gifOptions);
- }
+ ///
+ /// Gets or sets the encoding that should be used when writing comments.
+ ///
+ public Encoding TextEncoding { get; set; } = GifConstants.DefaultEncoding;
///
- /// Encodes the image to the specified stream from the .
+ /// Gets or sets the size of the color palette to use. For gifs the value ranges from 1 to 256. Leave as zero for default size.
///
- /// The pixel format.
- /// The to encode from.
- /// The to encode the image data to.
- /// The options for the encoder.
- public void Encode(Image image, Stream stream, IGifEncoderOptions options)
+ public int PaletteSize { get; set; } = 0;
+
+ ///
+ /// Gets or sets the transparency threshold.
+ ///
+ public byte Threshold { get; set; } = 128;
+
+ ///
+ /// Gets or sets the quantizer for reducing the color count.
+ ///
+ public IQuantizer Quantizer { get; set; }
+
+ ///
+ public void Encode(Image image, Stream stream)
where TPixel : struct, IPixel
{
- GifEncoderCore encoder = new GifEncoderCore(options);
+ GifEncoderCore encoder = new GifEncoderCore(this);
encoder.Encode(image, stream);
}
}
diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
index 5ef7ca165..81b3cfba4 100644
--- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
@@ -9,7 +9,7 @@ namespace ImageSharp.Formats
using System.Buffers;
using System.IO;
using System.Linq;
-
+ using System.Text;
using ImageSharp.PixelFormats;
using IO;
@@ -25,11 +25,6 @@ namespace ImageSharp.Formats
///
private readonly byte[] buffer = new byte[16];
- ///
- /// The options for the encoder.
- ///
- private readonly IGifEncoderOptions options;
-
///
/// The number of bits requires to store the image palette.
///
@@ -40,19 +35,44 @@ namespace ImageSharp.Formats
///
private bool hasFrames;
+ ///
+ /// Gets the TextEncoding
+ ///
+ private Encoding textEncoding;
+
+ ///
+ /// Gets or sets the quantizer for reducing the color count.
+ ///
+ private IQuantizer quantizer;
+
+ ///
+ /// Gets or sets the threshold.
+ ///
+ private byte threshold;
+
+ ///
+ /// Gets or sets the size of the color palette to use.
+ ///
+ private int paletteSize;
+
+ ///
+ /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
+ ///
+ private bool ignoreMetadata;
+
///
/// Initializes a new instance of the class.
///
/// The options for the encoder.
public GifEncoderCore(IGifEncoderOptions options)
{
- this.options = options ?? new GifEncoderOptions();
- }
+ this.textEncoding = options.TextEncoding ?? GifConstants.DefaultEncoding;
- ///
- /// Gets or sets the quantizer for reducing the color count.
- ///
- public IQuantizer Quantizer { get; set; }
+ this.quantizer = options.Quantizer;
+ this.threshold = options.Threshold;
+ this.paletteSize = options.PaletteSize;
+ this.ignoreMetadata = options.IgnoreMetadata;
+ }
///
/// Encodes the image to the specified stream from the .
@@ -66,26 +86,26 @@ namespace ImageSharp.Formats
Guard.NotNull(image, nameof(image));
Guard.NotNull(stream, nameof(stream));
- this.Quantizer = this.options.Quantizer ?? new OctreeQuantizer();
+ this.quantizer = this.quantizer ?? new OctreeQuantizer();
// Do not use IDisposable pattern here as we want to preserve the stream.
var writer = new EndianBinaryWriter(Endianness.LittleEndian, stream);
- // Ensure that quality can be set but has a fallback.
- int quality = this.options.Quality > 0 ? this.options.Quality : image.MetaData.Quality;
- quality = quality > 0 ? quality.Clamp(1, 256) : 256;
+ // Ensure that pallete size can be set but has a fallback.
+ int paletteSize = this.paletteSize;
+ paletteSize = paletteSize > 0 ? paletteSize.Clamp(1, 256) : 256;
// Get the number of bits.
- this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(quality);
+ this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(paletteSize);
- // Quantize the image returning a palette.
this.hasFrames = image.Frames.Any();
// Dithering when animating gifs is a bad idea as we introduce pixel tearing across frames.
- var ditheredQuantizer = (IQuantizer)this.Quantizer;
+ var ditheredQuantizer = (IQuantizer)this.quantizer;
ditheredQuantizer.Dither = !this.hasFrames;
- QuantizedImage quantized = ditheredQuantizer.Quantize(image, quality);
+ // Quantize the image returning a palette.
+ QuantizedImage quantized = ditheredQuantizer.Quantize(image, paletteSize);
int index = this.GetTransparentIndex(quantized);
@@ -111,7 +131,7 @@ namespace ImageSharp.Formats
for (int i = 0; i < image.Frames.Count; i++)
{
ImageFrame frame = image.Frames[i];
- QuantizedImage quantizedFrame = ditheredQuantizer.Quantize(frame, quality);
+ QuantizedImage quantizedFrame = ditheredQuantizer.Quantize(frame, paletteSize);
this.WriteGraphicalControlExtension(frame.MetaData, writer, this.GetTransparentIndex(quantizedFrame));
this.WriteImageDescriptor(frame, writer);
@@ -240,7 +260,7 @@ namespace ImageSharp.Formats
private void WriteComments(Image image, EndianBinaryWriter writer)
where TPixel : struct, IPixel
{
- if (this.options.IgnoreMetadata)
+ if (this.ignoreMetadata)
{
return;
}
@@ -251,7 +271,7 @@ namespace ImageSharp.Formats
return;
}
- byte[] comments = this.options.TextEncoding.GetBytes(property.Value);
+ byte[] comments = this.textEncoding.GetBytes(property.Value);
int count = Math.Min(comments.Length, 255);
diff --git a/src/ImageSharp/Formats/Gif/GifEncoderOptions.cs b/src/ImageSharp/Formats/Gif/GifEncoderOptions.cs
deleted file mode 100644
index 5d7c6e40b..000000000
--- a/src/ImageSharp/Formats/Gif/GifEncoderOptions.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-//
-// Copyright (c) James Jackson-South and contributors.
-// Licensed under the Apache License, Version 2.0.
-//
-
-namespace ImageSharp.Formats
-{
- using System.Text;
-
- using Quantizers;
-
- ///
- /// Encapsulates the options for the .
- ///
- public sealed class GifEncoderOptions : EncoderOptions, IGifEncoderOptions
- {
- ///
- /// Initializes a new instance of the class.
- ///
- public GifEncoderOptions()
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The options for the encoder.
- private GifEncoderOptions(IEncoderOptions options)
- : base(options)
- {
- }
-
- ///
- /// Gets or sets the encoding that should be used when writing comments.
- ///
- public Encoding TextEncoding { get; set; } = GifConstants.DefaultEncoding;
-
- ///
- /// Gets or sets the quality of output for images.
- ///
- /// For gifs the value ranges from 1 to 256.
- public int Quality { get; set; }
-
- ///
- /// Gets or sets the transparency threshold.
- ///
- public byte Threshold { get; set; } = 128;
-
- ///
- /// Gets or sets the quantizer for reducing the color count.
- ///
- public IQuantizer Quantizer { get; set; }
-
- ///
- /// Converts the options to a instance with a
- /// cast or by creating a new instance with the specfied options.
- ///
- /// The options for the encoder.
- /// The options for the .
- internal static IGifEncoderOptions Create(IEncoderOptions options)
- {
- return options as IGifEncoderOptions ?? new GifEncoderOptions(options);
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Gif/GifFormat.cs b/src/ImageSharp/Formats/Gif/GifFormat.cs
index 2851b0b6b..ea7b72d32 100644
--- a/src/ImageSharp/Formats/Gif/GifFormat.cs
+++ b/src/ImageSharp/Formats/Gif/GifFormat.cs
@@ -8,38 +8,20 @@ namespace ImageSharp.Formats
using System.Collections.Generic;
///
- /// Encapsulates the means to encode and decode gif images.
+ /// Registers the image encoders, decoders and mime type detectors for the jpeg format.
///
- public class GifFormat : IImageFormat
+ internal sealed class GifFormat : IImageFormat
{
///
- public string Extension => "gif";
+ public string Name => "GIF";
///
- public string MimeType => "image/gif";
+ public string DefaultMimeType => "image/gif";
///
- public IEnumerable SupportedExtensions => new string[] { "gif" };
+ public IEnumerable MimeTypes => GifConstants.MimeTypes;
///
- public IImageDecoder Decoder => new GifDecoder();
-
- ///
- public IImageEncoder Encoder => new GifEncoder();
-
- ///
- public int HeaderSize => 6;
-
- ///
- public bool IsSupportedFileFormat(byte[] header)
- {
- return header.Length >= this.HeaderSize &&
- header[0] == 0x47 && // G
- header[1] == 0x49 && // I
- header[2] == 0x46 && // F
- header[3] == 0x38 && // 8
- (header[4] == 0x39 || header[4] == 0x37) && // 9 or 7
- header[5] == 0x61; // a
- }
+ public IEnumerable FileExtensions => GifConstants.FileExtensions;
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Gif/GifImageFormatDetector.cs b/src/ImageSharp/Formats/Gif/GifImageFormatDetector.cs
new file mode 100644
index 000000000..04fcfc516
--- /dev/null
+++ b/src/ImageSharp/Formats/Gif/GifImageFormatDetector.cs
@@ -0,0 +1,41 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Formats
+{
+ using System;
+
+ ///
+ /// Detects gif file headers
+ ///
+ public sealed class GifImageFormatDetector : IImageFormatDetector
+ {
+ ///
+ public int HeaderSize => 6;
+
+ ///
+ public IImageFormat DetectFormat(ReadOnlySpan header)
+ {
+ if (this.IsSupportedFileFormat(header))
+ {
+ return ImageFormats.Gif;
+ }
+
+ return null;
+ }
+
+ private bool IsSupportedFileFormat(ReadOnlySpan header)
+ {
+ // TODO: This should be in constants
+ return header.Length >= this.HeaderSize &&
+ header[0] == 0x47 && // G
+ header[1] == 0x49 && // I
+ header[2] == 0x46 && // F
+ header[3] == 0x38 && // 8
+ (header[4] == 0x39 || header[4] == 0x37) && // 9 or 7
+ header[5] == 0x61; // a
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Gif/IGifDecoderOptions.cs b/src/ImageSharp/Formats/Gif/IGifDecoderOptions.cs
index 729bf1d11..caaa8932b 100644
--- a/src/ImageSharp/Formats/Gif/IGifDecoderOptions.cs
+++ b/src/ImageSharp/Formats/Gif/IGifDecoderOptions.cs
@@ -1,17 +1,26 @@
-//
+//
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
//
namespace ImageSharp.Formats
{
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
using System.Text;
+ using ImageSharp.PixelFormats;
///
- /// Encapsulates the options for the .
+ /// Decoder for generating an image out of a gif encoded stream.
///
- public interface IGifDecoderOptions : IDecoderOptions
+ internal interface IGifDecoderOptions
{
+ ///
+ /// Gets a value indicating whether the metadata should be ignored when the image is being decoded.
+ ///
+ bool IgnoreMetadata { get; }
+
///
/// Gets the encoding that should be used when reading comments.
///
diff --git a/src/ImageSharp/Formats/Gif/IGifEncoderOptions.cs b/src/ImageSharp/Formats/Gif/IGifEncoderOptions.cs
index c1d6b7ad8..c38ec7e45 100644
--- a/src/ImageSharp/Formats/Gif/IGifEncoderOptions.cs
+++ b/src/ImageSharp/Formats/Gif/IGifEncoderOptions.cs
@@ -1,29 +1,36 @@
-//
+//
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
//
namespace ImageSharp.Formats
{
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
using System.Text;
-
- using Quantizers;
+ using ImageSharp.PixelFormats;
+ using ImageSharp.Quantizers;
///
- /// Encapsulates the options for the .
+ /// The configuration options used for encoding gifs
///
- public interface IGifEncoderOptions : IEncoderOptions
+ internal interface IGifEncoderOptions
{
+ ///
+ /// Gets a value indicating whether the metadata should be ignored when the image is being encoded.
+ ///
+ bool IgnoreMetadata { get; }
+
///
/// Gets the encoding that should be used when writing comments.
///
Encoding TextEncoding { get; }
///
- /// Gets the quality of output for images.
+ /// Gets the size of the color palette to use. For gifs the value ranges from 1 to 256. Leave as zero for default size.
///
- /// For gifs the value ranges from 1 to 256.
- int Quality { get; }
+ int PaletteSize { get; }
///
/// Gets the transparency threshold.
@@ -33,6 +40,6 @@ namespace ImageSharp.Formats
///
/// Gets the quantizer for reducing the color count.
///
- IQuantizer Quantizer { get; }
+ IQuantizer Quantizer { get; }
}
}
diff --git a/src/ImageSharp/Formats/Gif/ImageExtensions.cs b/src/ImageSharp/Formats/Gif/ImageExtensions.cs
index d64203f6c..ea9c9b504 100644
--- a/src/ImageSharp/Formats/Gif/ImageExtensions.cs
+++ b/src/ImageSharp/Formats/Gif/ImageExtensions.cs
@@ -39,16 +39,16 @@ namespace ImageSharp
/// The pixel format.
/// The image this method extends.
/// The stream to save the image to.
- /// The options for the encoder.
+ /// The options for the encoder.
/// Thrown if the stream is null.
///
/// The .
///
- public static Image SaveAsGif(this Image source, Stream stream, IGifEncoderOptions options)
+ public static Image SaveAsGif(this Image source, Stream stream, GifEncoder encoder)
where TPixel : struct, IPixel
{
- GifEncoder encoder = new GifEncoder();
- encoder.Encode(source, stream, options);
+ encoder = encoder ?? new GifEncoder();
+ encoder.Encode(source, stream);
return source;
}
diff --git a/src/ImageSharp/Formats/IEncoderOptions.cs b/src/ImageSharp/Formats/IEncoderOptions.cs
deleted file mode 100644
index 0fd3d1c43..000000000
--- a/src/ImageSharp/Formats/IEncoderOptions.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-//
-// Copyright (c) James Jackson-South and contributors.
-// Licensed under the Apache License, Version 2.0.
-//
-
-namespace ImageSharp
-{
- ///
- /// Encapsulates the shared encoder options.
- ///
- public interface IEncoderOptions
- {
- ///
- /// Gets a value indicating whether the metadata should be ignored when the image is being encoded.
- ///
- bool IgnoreMetadata { get; }
- }
-}
diff --git a/src/ImageSharp/Formats/IImageDecoder.cs b/src/ImageSharp/Formats/IImageDecoder.cs
index 4fd25df13..66eabb1b8 100644
--- a/src/ImageSharp/Formats/IImageDecoder.cs
+++ b/src/ImageSharp/Formats/IImageDecoder.cs
@@ -6,6 +6,7 @@
namespace ImageSharp.Formats
{
using System;
+ using System.Collections.Generic;
using System.IO;
using ImageSharp.PixelFormats;
@@ -21,9 +22,8 @@ namespace ImageSharp.Formats
/// The pixel format.
/// The configuration for the image.
/// The containing image data.
- /// The options for the decoder.
/// The decoded image
- Image Decode(Configuration configuration, Stream stream, IDecoderOptions options)
+ Image Decode(Configuration configuration, Stream stream)
where TPixel : struct, IPixel;
}
}
diff --git a/src/ImageSharp/Formats/IImageEncoder.cs b/src/ImageSharp/Formats/IImageEncoder.cs
index a28511c17..4ad41ebc2 100644
--- a/src/ImageSharp/Formats/IImageEncoder.cs
+++ b/src/ImageSharp/Formats/IImageEncoder.cs
@@ -6,6 +6,7 @@
namespace ImageSharp.Formats
{
using System;
+ using System.Collections.Generic;
using System.IO;
using ImageSharp.PixelFormats;
@@ -21,8 +22,7 @@ namespace ImageSharp.Formats
/// The pixel format.
/// The to encode from.
/// The to encode the image data to.
- /// The options for the encoder.
- void Encode(Image image, Stream stream, IEncoderOptions options)
+ void Encode(Image image, Stream stream)
where TPixel : struct, IPixel;
}
}
diff --git a/src/ImageSharp/Formats/IImageFormat.cs b/src/ImageSharp/Formats/IImageFormat.cs
index de2e400fa..d6ddc0b0b 100644
--- a/src/ImageSharp/Formats/IImageFormat.cs
+++ b/src/ImageSharp/Formats/IImageFormat.cs
@@ -8,53 +8,28 @@ namespace ImageSharp.Formats
using System.Collections.Generic;
///
- /// Encapsulates a supported image format, providing means to encode and decode an image.
- /// Individual formats implements in this interface must be registered in the
+ /// Describes an image format.
///
public interface IImageFormat
{
///
- /// Gets the standard identifier used on the Internet to indicate the type of data that a file contains.
+ /// Gets the name that describes this image format.
///
- string MimeType { get; }
+ string Name { get; }
///
- /// Gets the default file extension for this format.
+ /// Gets the default mimetype that the image foramt uses
///
- string Extension { get; }
+ string DefaultMimeType { get; }
///
- /// Gets the supported file extensions for this format.
+ /// Gets all the mimetypes that have been used by this image foramt.
///
- ///
- /// The supported file extension.
- ///
- IEnumerable SupportedExtensions { get; }
+ IEnumerable MimeTypes { get; }
///
- /// Gets the image encoder for encoding an image from a stream.
+ /// Gets the file extensions this image format commonly uses.
///
- IImageEncoder Encoder { get; }
-
- ///
- /// Gets the image decoder for decoding an image from a stream.
- ///
- IImageDecoder Decoder { get; }
-
- ///
- /// Gets the size of the header for this image type.
- ///
- /// The size of the header.
- int HeaderSize { get; }
-
- ///
- /// Returns a value indicating whether the supports the specified
- /// file header.
- ///
- /// The containing the file header.
- ///
- /// True if the decoder supports the file header; otherwise, false.
- ///
- bool IsSupportedFileFormat(byte[] header);
+ IEnumerable FileExtensions { get; }
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/IImageFormatDetector.cs b/src/ImageSharp/Formats/IImageFormatDetector.cs
new file mode 100644
index 000000000..a53da07e8
--- /dev/null
+++ b/src/ImageSharp/Formats/IImageFormatDetector.cs
@@ -0,0 +1,30 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Formats
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Text;
+
+ ///
+ /// Used for detecting mime types from a file header
+ ///
+ public interface IImageFormatDetector
+ {
+ ///
+ /// Gets the size of the header for this image type.
+ ///
+ /// The size of the header.
+ int HeaderSize { get; }
+
+ ///
+ /// Detect mimetype
+ ///
+ /// The containing the file header.
+ /// returns the mime type of detected othersie returns null
+ IImageFormat DetectFormat(ReadOnlySpan header);
+ }
+}
diff --git a/src/ImageSharp/Formats/IDecoderOptions.cs b/src/ImageSharp/Formats/Jpeg/IJpegDecoderOptions.cs
similarity index 53%
rename from src/ImageSharp/Formats/IDecoderOptions.cs
rename to src/ImageSharp/Formats/Jpeg/IJpegDecoderOptions.cs
index cdfd90d5e..6830e2e4a 100644
--- a/src/ImageSharp/Formats/IDecoderOptions.cs
+++ b/src/ImageSharp/Formats/Jpeg/IJpegDecoderOptions.cs
@@ -1,14 +1,20 @@
-//
+//
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
//
-namespace ImageSharp
+namespace ImageSharp.Formats
{
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+
+ using ImageSharp.PixelFormats;
+
///
- /// Encapsulates the shared decoder options.
+ /// Image decoder for generating an image out of a jpg stream.
///
- public interface IDecoderOptions
+ internal interface IJpegDecoderOptions
{
///
/// Gets a value indicating whether the metadata should be ignored when the image is being decoded.
diff --git a/src/ImageSharp/Formats/Jpeg/IJpegEncoderOptions.cs b/src/ImageSharp/Formats/Jpeg/IJpegEncoderOptions.cs
index a54517965..947c98ee2 100644
--- a/src/ImageSharp/Formats/Jpeg/IJpegEncoderOptions.cs
+++ b/src/ImageSharp/Formats/Jpeg/IJpegEncoderOptions.cs
@@ -1,15 +1,26 @@
-//
+//
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
//
namespace ImageSharp.Formats
{
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+
+ using ImageSharp.PixelFormats;
+
///
- /// Encapsulates the options for the .
+ /// Encoder for writing the data image to a stream in jpeg format.
///
- public interface IJpegEncoderOptions : IEncoderOptions
+ internal interface IJpegEncoderOptions
{
+ ///
+ /// Gets a value indicating whether the metadata should be ignored when the image is being decoded.
+ ///
+ bool IgnoreMetadata { get; }
+
///
/// Gets the quality, that will be used to encode the image. Quality
/// index must be between 0 and 100 (compression from max to min).
diff --git a/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs b/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs
index 420af6b74..8fbf9e5a7 100644
--- a/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs
+++ b/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs
@@ -39,16 +39,16 @@ namespace ImageSharp
/// The pixel format.
/// The image this method extends.
/// The stream to save the image to.
- /// The options for the encoder.
+ /// The options for the encoder.
/// Thrown if the stream is null.
///
/// The .
///
- public static Image SaveAsJpeg(this Image source, Stream stream, IJpegEncoderOptions options)
+ public static Image SaveAsJpeg(this Image source, Stream stream, JpegEncoder encoder)
where TPixel : struct, IPixel
{
- JpegEncoder encoder = new JpegEncoder();
- encoder.Encode(source, stream, options);
+ encoder = encoder ?? new JpegEncoder();
+ encoder.Encode(source, stream);
return source;
}
diff --git a/src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs b/src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs
new file mode 100644
index 000000000..bb8c4e83f
--- /dev/null
+++ b/src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs
@@ -0,0 +1,22 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Formats
+{
+ ///
+ /// Registers the image encoders, decoders and mime type detectors for the jpeg format.
+ ///
+ public sealed class JpegConfigurationModule : IConfigurationModule
+ {
+ ///
+ public void Configure(Configuration config)
+ {
+ config.SetEncoder(ImageFormats.Jpeg, new JpegEncoder());
+ config.SetDecoder(ImageFormats.Jpeg, new JpegDecoder());
+
+ config.AddImageFormatDetector(new JpegImageFormatDetector());
+ }
+ }
+}
diff --git a/src/ImageSharp/Formats/Jpeg/JpegConstants.cs b/src/ImageSharp/Formats/Jpeg/JpegConstants.cs
index dcda39842..99c0399dc 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegConstants.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegConstants.cs
@@ -5,6 +5,8 @@
namespace ImageSharp.Formats
{
+ using System.Collections.Generic;
+
///
/// Defines jpeg constants defined in the specification.
///
@@ -15,6 +17,16 @@ namespace ImageSharp.Formats
///
public const ushort MaxLength = 65535;
+ ///
+ /// The list of mimetypes that equate to a jpeg.
+ ///
+ public static readonly IEnumerable MimeTypes = new[] { "image/jpeg", "image/pjpeg" };
+
+ ///
+ /// The list of file extensions that equate to a jpeg.
+ ///
+ public static readonly IEnumerable FileExtensions = new[] { "jpg", "jpeg", "jfif" };
+
///
/// Represents high detail chroma horizontal subsampling.
///
diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs
index 33d82ace8..38160c148 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs
@@ -5,7 +5,6 @@
namespace ImageSharp.Formats
{
- using System;
using System.IO;
using ImageSharp.PixelFormats;
@@ -13,22 +12,24 @@ namespace ImageSharp.Formats
///
/// Image decoder for generating an image out of a jpg stream.
///
- public class JpegDecoder : IImageDecoder
+ public sealed class JpegDecoder : IImageDecoder, IJpegDecoderOptions
{
+ ///
+ /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
+ ///
+ public bool IgnoreMetadata { get; set; }
+
///
- public Image Decode(Configuration configuration, Stream stream, IDecoderOptions options)
+ public Image Decode(Configuration configuration, Stream stream)
where TPixel : struct, IPixel
{
Guard.NotNull(stream, "stream");
- // using (var decoder = new JpegDecoderCore(options, configuration))
- // {
- // return decoder.Decode(stream);
- // }
- using (var decoder = new Jpeg.Port.JpegDecoderCore(options, configuration))
+ // using (var decoder = new JpegDecoderCore(configuration, this))
+ using (var decoder = new Jpeg.Port.JpegDecoderCore(configuration, this))
{
return decoder.Decode(stream);
}
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
index 971684371..0ce927e51 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
@@ -18,7 +18,7 @@ namespace ImageSharp.Formats
///
/// Performs the jpeg decoding operation.
///
- internal unsafe class JpegDecoderCore : IDisposable
+ internal sealed unsafe class JpegDecoderCore : IDisposable
{
///
/// The maximum number of color components
@@ -45,11 +45,6 @@ namespace ImageSharp.Formats
///
private static YCbCrToRgbTables yCbCrToRgbTables = YCbCrToRgbTables.Create();
- ///
- /// The decoder options.
- ///
- private readonly IDecoderOptions options;
-
///
/// The global configuration
///
@@ -103,12 +98,12 @@ namespace ImageSharp.Formats
///
/// Initializes a new instance of the class.
///
- /// The decoder options.
/// The configuration.
- public JpegDecoderCore(IDecoderOptions options, Configuration configuration)
+ /// The options.
+ public JpegDecoderCore(Configuration configuration, IJpegDecoderOptions options)
{
+ this.IgnoreMetadata = options.IgnoreMetadata;
this.configuration = configuration ?? Configuration.Default;
- this.options = options ?? new DecoderOptions();
this.HuffmanTrees = HuffmanTree.CreateHuffmanTrees();
this.QuantizationTables = new Block8x8F[MaxTq + 1];
this.Temp = new byte[2 * Block8x8F.ScalarCount];
@@ -190,6 +185,11 @@ namespace ImageSharp.Formats
///
public int TotalMCUCount => this.MCUCountX * this.MCUCountY;
+ ///
+ /// Gets a value indicating whether the metadata should be ignored when the image is being decoded.
+ ///
+ public bool IgnoreMetadata { get; private set; }
+
///
/// Decodes the image from the specified and sets
/// the data to image.
@@ -938,7 +938,7 @@ namespace ImageSharp.Formats
/// The image.
private void ProcessApp1Marker(int remaining, ImageMetaData metadata)
{
- if (remaining < 6 || this.options.IgnoreMetadata)
+ if (remaining < 6 || this.IgnoreMetadata)
{
this.InputProcessor.Skip(remaining);
return;
@@ -968,7 +968,7 @@ namespace ImageSharp.Formats
{
// Length is 14 though we only need to check 12.
const int Icclength = 14;
- if (remaining < Icclength || this.options.IgnoreMetadata)
+ if (remaining < Icclength || this.IgnoreMetadata)
{
this.InputProcessor.Skip(remaining);
return;
diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs
index 152fd2c64..6c6561468 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs
@@ -5,6 +5,8 @@
namespace ImageSharp.Formats
{
+ using System;
+ using System.Collections.Generic;
using System.IO;
using ImageSharp.PixelFormats;
@@ -12,16 +14,25 @@ namespace ImageSharp.Formats
///
/// Encoder for writing the data image to a stream in jpeg format.
///
- public class JpegEncoder : IImageEncoder
+ public sealed class JpegEncoder : IImageEncoder, IJpegEncoderOptions
{
- ///
- public void Encode(Image image, Stream stream, IEncoderOptions options)
- where TPixel : struct, IPixel
- {
- IJpegEncoderOptions gifOptions = JpegEncoderOptions.Create(options);
+ ///
+ /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
+ ///
+ public bool IgnoreMetadata { get; set; }
- this.Encode(image, stream, gifOptions);
- }
+ ///
+ /// Gets or sets the quality, that will be used to encode the image. Quality
+ /// index must be between 0 and 100 (compression from max to min).
+ ///
+ /// The quality of the jpg image from 0 to 100.
+ public int Quality { get; set; }
+
+ ///
+ /// Gets or sets the subsample ration, that will be used to encode the image.
+ ///
+ /// The subsample ratio of the jpg image.
+ public JpegSubsample? Subsample { get; set; }
///
/// Encodes the image to the specified stream from the .
@@ -29,12 +40,11 @@ namespace ImageSharp.Formats
/// The pixel format.
/// The to encode from.
/// The to encode the image data to.
- /// The options for the encoder.
- public void Encode(Image image, Stream stream, IJpegEncoderOptions options)
- where TPixel : struct, IPixel
+ public void Encode(Image image, Stream stream)
+ where TPixel : struct, IPixel
{
- JpegEncoderCore encode = new JpegEncoderCore(options);
- encode.Encode(image, stream);
+ var encoder = new JpegEncoderCore(this);
+ encoder.Encode(image, stream);
}
}
}
diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
index b65a56e73..d2b7d2d7c 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
@@ -17,7 +17,7 @@ namespace ImageSharp.Formats
///
/// Image encoder for writing an image to a stream as a jpeg.
///
- internal unsafe class JpegEncoderCore
+ internal sealed unsafe class JpegEncoderCore
{
///
/// The number of quantization tables.
@@ -124,11 +124,6 @@ namespace ImageSharp.Formats
///
private readonly byte[] huffmanBuffer = new byte[179];
- ///
- /// The options for the encoder.
- ///
- private readonly IJpegEncoderOptions options;
-
///
/// The accumulated bits to write to the stream.
///
@@ -155,17 +150,38 @@ namespace ImageSharp.Formats
private Stream outputStream;
///
- /// The subsampling method to use.
+ /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
+ ///
+ private bool ignoreMetadata = false;
+
+ ///
+ /// Gets or sets the quality, that will be used to encode the image. Quality
+ /// index must be between 0 and 100 (compression from max to min).
///
- private JpegSubsample subsample;
+ /// The quality of the jpg image from 0 to 100.
+ private int quality = 0;
+
+ ///
+ /// Gets or sets the subsampling method to use.
+ ///
+ private JpegSubsample? subsample;
///
/// Initializes a new instance of the class.
///
- /// The options for the encoder.
+ /// The options
public JpegEncoderCore(IJpegEncoderOptions options)
{
- this.options = options ?? new JpegEncoderOptions();
+ int quality = options.Quality;
+ if (quality == 0)
+ {
+ quality = 75;
+ }
+
+ this.quality = quality;
+ this.subsample = options.Subsample ?? (quality >= 91 ? JpegSubsample.Ratio444 : JpegSubsample.Ratio420);
+
+ this.ignoreMetadata = options.IgnoreMetadata;
}
///
@@ -186,21 +202,13 @@ namespace ImageSharp.Formats
throw new ImageFormatException($"Image is too large to encode at {image.Width}x{image.Height}.");
}
- // Ensure that quality can be set but has a fallback.
- int quality = this.options.Quality > 0 ? this.options.Quality : image.MetaData.Quality;
- if (quality == 0)
- {
- quality = 75;
- }
-
- quality = quality.Clamp(1, 100);
-
this.outputStream = stream;
- this.subsample = this.options.Subsample ?? (quality >= 91 ? JpegSubsample.Ratio444 : JpegSubsample.Ratio420);
+
+ int quality = this.quality.Clamp(1, 100);
// Convert from a quality rating to a scaling factor.
int scale;
- if (quality < 50)
+ if (this.quality < 50)
{
scale = 5000 / quality;
}
@@ -788,7 +796,7 @@ namespace ImageSharp.Formats
private void WriteProfiles(Image image)
where TPixel : struct, IPixel
{
- if (this.options.IgnoreMetadata)
+ if (this.ignoreMetadata)
{
return;
}
diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoderOptions.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoderOptions.cs
deleted file mode 100644
index 73e483164..000000000
--- a/src/ImageSharp/Formats/Jpeg/JpegEncoderOptions.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// Copyright (c) James Jackson-South and contributors.
-// Licensed under the Apache License, Version 2.0.
-//
-
-namespace ImageSharp.Formats
-{
- ///
- /// Encapsulates the options for the .
- ///
- public sealed class JpegEncoderOptions : EncoderOptions, IJpegEncoderOptions
- {
- ///
- /// Initializes a new instance of the class.
- ///
- public JpegEncoderOptions()
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The options for the encoder.
- private JpegEncoderOptions(IEncoderOptions options)
- : base(options)
- {
- }
-
- ///
- /// Gets or sets the quality, that will be used to encode the image. Quality
- /// index must be between 0 and 100 (compression from max to min).
- ///
- ///
- /// If the quality is less than or equal to 90, the subsampling ratio will switch to
- ///
- /// The quality of the jpg image from 0 to 100.
- public int Quality { get; set; }
-
- ///
- /// Gets or sets the subsample ration, that will be used to encode the image.
- ///
- /// The subsample ratio of the jpg image.
- public JpegSubsample? Subsample { get; set; }
-
- ///
- /// Converts the options to a instance with a
- /// cast or by creating a new instance with the specfied options.
- ///
- /// The options for the encoder.
- /// The options for the .
- internal static IJpegEncoderOptions Create(IEncoderOptions options)
- {
- return options as IJpegEncoderOptions ?? new JpegEncoderOptions(options);
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Jpeg/JpegFormat.cs b/src/ImageSharp/Formats/Jpeg/JpegFormat.cs
index b93c6ae69..23cd5d875 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegFormat.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegFormat.cs
@@ -8,82 +8,20 @@ namespace ImageSharp.Formats
using System.Collections.Generic;
///
- /// Encapsulates the means to encode and decode jpeg images.
+ /// Registers the image encoders, decoders and mime type detectors for the jpeg format.
///
- public class JpegFormat : IImageFormat
+ internal sealed class JpegFormat : IImageFormat
{
///
- public string MimeType => "image/jpeg";
+ public string Name => "JPEG";
///
- public string Extension => "jpg";
+ public string DefaultMimeType => "image/jpeg";
///
- public IEnumerable SupportedExtensions => new string[] { "jpg", "jpeg", "jfif" };
+ public IEnumerable MimeTypes => JpegConstants.MimeTypes;
///
- public IImageDecoder Decoder => new JpegDecoder();
-
- ///
- public IImageEncoder Encoder => new JpegEncoder();
-
- ///
- public int HeaderSize => 11;
-
- ///
- public bool IsSupportedFileFormat(byte[] header)
- {
- return header.Length >= this.HeaderSize &&
- (IsJfif(header) || IsExif(header) || IsJpeg(header));
- }
-
- ///
- /// Returns a value indicating whether the given bytes identify Jfif data.
- ///
- /// The bytes representing the file header.
- /// The
- private static bool IsJfif(byte[] header)
- {
- bool isJfif =
- header[6] == 0x4A && // J
- header[7] == 0x46 && // F
- header[8] == 0x49 && // I
- header[9] == 0x46 && // F
- header[10] == 0x00;
-
- return isJfif;
- }
-
- ///
- /// Returns a value indicating whether the given bytes identify EXIF data.
- ///
- /// The bytes representing the file header.
- /// The
- private static bool IsExif(byte[] header)
- {
- bool isExif =
- header[6] == 0x45 && // E
- header[7] == 0x78 && // X
- header[8] == 0x69 && // I
- header[9] == 0x66 && // F
- header[10] == 0x00;
-
- return isExif;
- }
-
- ///
- /// Returns a value indicating whether the given bytes identify Jpeg data.
- /// This is a last chance resort for jpegs that contain ICC information.
- ///
- /// The bytes representing the file header.
- /// The
- private static bool IsJpeg(byte[] header)
- {
- bool isJpg =
- header[0] == 0xFF && // 255
- header[1] == 0xD8; // 216
-
- return isJpg;
- }
+ public IEnumerable FileExtensions => JpegConstants.FileExtensions;
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs b/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs
new file mode 100644
index 000000000..b72b290c0
--- /dev/null
+++ b/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs
@@ -0,0 +1,87 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Formats
+{
+ using System;
+
+ ///
+ /// Detects Jpeg file headers
+ ///
+ public sealed class JpegImageFormatDetector : IImageFormatDetector
+ {
+ ///
+ public int HeaderSize => 11;
+
+ ///
+ public IImageFormat DetectFormat(ReadOnlySpan header)
+ {
+ if (this.IsSupportedFileFormat(header))
+ {
+ return ImageFormats.Jpeg;
+ }
+
+ return null;
+ }
+
+ private bool IsSupportedFileFormat(ReadOnlySpan header)
+ {
+ return header.Length >= this.HeaderSize &&
+ (this.IsJfif(header) || this.IsExif(header) || this.IsJpeg(header));
+ }
+
+ ///
+ /// Returns a value indicating whether the given bytes identify Jfif data.
+ ///
+ /// The bytes representing the file header.
+ /// The
+ private bool IsJfif(ReadOnlySpan header)
+ {
+ // TODO: This should be in constants
+ bool isJfif =
+ header[6] == 0x4A && // J
+ header[7] == 0x46 && // F
+ header[8] == 0x49 && // I
+ header[9] == 0x46 && // F
+ header[10] == 0x00;
+
+ return isJfif;
+ }
+
+ ///
+ /// Returns a value indicating whether the given bytes identify EXIF data.
+ ///
+ /// The bytes representing the file header.
+ /// The
+ private bool IsExif(ReadOnlySpan header)
+ {
+ // TODO: This should be in constants
+ bool isExif =
+ header[6] == 0x45 && // E
+ header[7] == 0x78 && // X
+ header[8] == 0x69 && // I
+ header[9] == 0x66 && // F
+ header[10] == 0x00;
+
+ return isExif;
+ }
+
+ ///
+ /// Returns a value indicating whether the given bytes identify Jpeg data.
+ /// This is a last chance resort for jpegs that contain ICC information.
+ ///
+ /// The bytes representing the file header.
+ /// The
+ private bool IsJpeg(ReadOnlySpan header)
+ {
+ // TODO: This should be in constants
+ bool isJpg =
+ header[0] == 0xFF && // 255
+ header[1] == 0xD8; // 216
+
+ return isJpg;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/Port/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/Port/JpegDecoderCore.cs
index ca93e96dd..f0e05fabd 100644
--- a/src/ImageSharp/Formats/Jpeg/Port/JpegDecoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/Port/JpegDecoderCore.cs
@@ -22,11 +22,6 @@ namespace ImageSharp.Formats.Jpeg.Port
///
internal sealed class JpegDecoderCore : IDisposable
{
- ///
- /// The decoder options.
- ///
- private readonly IDecoderOptions options;
-
///
/// The global configuration
///
@@ -85,12 +80,12 @@ namespace ImageSharp.Formats.Jpeg.Port
///
/// Initializes a new instance of the class.
///
- /// The decoder options.
/// The configuration.
- public JpegDecoderCore(IDecoderOptions options, Configuration configuration)
+ /// The options.
+ public JpegDecoderCore(Configuration configuration, IJpegDecoderOptions options)
{
this.configuration = configuration ?? Configuration.Default;
- this.options = options ?? new DecoderOptions();
+ this.IgnoreMetadata = options.IgnoreMetadata;
}
///
@@ -98,6 +93,11 @@ namespace ImageSharp.Formats.Jpeg.Port
///
public Stream InputStream { get; private set; }
+ ///
+ /// Gets a value indicating whether the metadata should be ignored when the image is being decoded.
+ ///
+ public bool IgnoreMetadata { get; }
+
///
/// Finds the next file marker within the byte stream.
///
@@ -413,7 +413,7 @@ namespace ImageSharp.Formats.Jpeg.Port
/// The image.
private void ProcessApp1Marker(int remaining, ImageMetaData metadata)
{
- if (remaining < 6 || this.options.IgnoreMetadata)
+ if (remaining < 6 || this.IgnoreMetadata)
{
// Skip the application header length
this.InputStream.Skip(remaining);
@@ -444,7 +444,7 @@ namespace ImageSharp.Formats.Jpeg.Port
{
// Length is 14 though we only need to check 12.
const int Icclength = 14;
- if (remaining < Icclength || this.options.IgnoreMetadata)
+ if (remaining < Icclength || this.IgnoreMetadata)
{
this.InputStream.Skip(remaining);
return;
diff --git a/src/ImageSharp/Formats/Png/IPngDecoderOptions.cs b/src/ImageSharp/Formats/Png/IPngDecoderOptions.cs
index cc6d194bf..de163ba7e 100644
--- a/src/ImageSharp/Formats/Png/IPngDecoderOptions.cs
+++ b/src/ImageSharp/Formats/Png/IPngDecoderOptions.cs
@@ -1,17 +1,26 @@
-//
+//
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
//
namespace ImageSharp.Formats
{
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
using System.Text;
+ using ImageSharp.PixelFormats;
///
- /// Encapsulates the options for the .
+ /// The optioas for decoding png images
///
- public interface IPngDecoderOptions : IDecoderOptions
+ internal interface IPngDecoderOptions
{
+ ///
+ /// Gets a value indicating whether the metadata should be ignored when the image is being decoded.
+ ///
+ bool IgnoreMetadata { get; }
+
///
/// Gets the encoding that should be used when reading text chunks.
///
diff --git a/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs b/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs
index 0008080d3..8f0a4cd82 100644
--- a/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs
+++ b/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs
@@ -1,21 +1,30 @@
-//
+//
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
//
namespace ImageSharp.Formats
{
- using Quantizers;
+ using System.Collections.Generic;
+ using System.IO;
+
+ using ImageSharp.PixelFormats;
+ using ImageSharp.Quantizers;
///
- /// Encapsulates the options for the .
+ /// The options availible for manipulating the encoder pipeline
///
- public interface IPngEncoderOptions : IEncoderOptions
+ internal interface IPngEncoderOptions
{
///
- /// Gets the quality of output for images.
+ /// Gets a value indicating whether the metadata should be ignored when the image is being encoded.
+ ///
+ bool IgnoreMetadata { get; }
+
+ ///
+ /// Gets the size of the color palette to use. Set to zero to leav png encoding to use pixel data.
///
- int Quality { get; }
+ int PaletteSize { get; }
///
/// Gets the png color type
@@ -24,19 +33,20 @@ namespace ImageSharp.Formats
///
/// Gets the compression level 1-9.
+ /// Defaults to 6.
///
int CompressionLevel { get; }
///
/// Gets the gamma value, that will be written
/// the the stream, when the property
- /// is set to true.
+ /// is set to true. The default value is 2.2F.
///
/// The gamma value of the image.
float Gamma { get; }
///
- /// Gets quantizer for reducing the color count.
+ /// Gets quantizer for reducing the color count.
///
IQuantizer Quantizer { get; }
@@ -47,7 +57,7 @@ namespace ImageSharp.Formats
///
/// Gets a value indicating whether this instance should write
- /// gamma information to the stream.
+ /// gamma information to the stream. The default value is false.
///
bool WriteGamma { get; }
}
diff --git a/src/ImageSharp/Formats/Png/ImageExtensions.cs b/src/ImageSharp/Formats/Png/ImageExtensions.cs
index 3841b313c..c81738576 100644
--- a/src/ImageSharp/Formats/Png/ImageExtensions.cs
+++ b/src/ImageSharp/Formats/Png/ImageExtensions.cs
@@ -38,16 +38,16 @@ namespace ImageSharp
/// The pixel format.
/// The image this method extends.
/// The stream to save the image to.
- /// The options for the encoder.
+ /// The options for the encoder.
/// Thrown if the stream is null.
///
/// The .
///
- public static Image SaveAsPng(this Image source, Stream stream, IPngEncoderOptions options)
+ public static Image SaveAsPng(this Image source, Stream stream, PngEncoder encoder)
where TPixel : struct, IPixel
{
- var encoder = new PngEncoder();
- encoder.Encode(source, stream, options);
+ encoder = encoder ?? new PngEncoder();
+ encoder.Encode(source, stream);
return source;
}
diff --git a/src/ImageSharp/Formats/Png/PngConfigurationModule.cs b/src/ImageSharp/Formats/Png/PngConfigurationModule.cs
new file mode 100644
index 000000000..bb1c2086c
--- /dev/null
+++ b/src/ImageSharp/Formats/Png/PngConfigurationModule.cs
@@ -0,0 +1,21 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Formats
+{
+ ///
+ /// Registers the image encoders, decoders and mime type detectors for the png format.
+ ///
+ public sealed class PngConfigurationModule : IConfigurationModule
+ {
+ ///
+ public void Configure(Configuration host)
+ {
+ host.SetEncoder(ImageFormats.Png, new PngEncoder());
+ host.SetDecoder(ImageFormats.Png, new PngDecoder());
+ host.AddImageFormatDetector(new PngImageFormatDetector());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Png/PngConstants.cs b/src/ImageSharp/Formats/Png/PngConstants.cs
new file mode 100644
index 000000000..84e76a341
--- /dev/null
+++ b/src/ImageSharp/Formats/Png/PngConstants.cs
@@ -0,0 +1,31 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Formats
+{
+ using System.Collections.Generic;
+ using System.Text;
+
+ ///
+ /// Defines png constants defined in the specification.
+ ///
+ internal static class PngConstants
+ {
+ ///
+ /// The default encoding for text metadata.
+ ///
+ public static readonly Encoding DefaultEncoding = Encoding.GetEncoding("ASCII");
+
+ ///
+ /// The list of mimetypes that equate to a png.
+ ///
+ public static readonly IEnumerable MimeTypes = new[] { "image/png" };
+
+ ///
+ /// The list of file extensions that equate to a png.
+ ///
+ public static readonly IEnumerable FileExtensions = new[] { "png" };
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Png/PngDecoder.cs b/src/ImageSharp/Formats/Png/PngDecoder.cs
index 3a34147e2..61a8cb212 100644
--- a/src/ImageSharp/Formats/Png/PngDecoder.cs
+++ b/src/ImageSharp/Formats/Png/PngDecoder.cs
@@ -6,8 +6,9 @@
namespace ImageSharp.Formats
{
using System;
+ using System.Collections.Generic;
using System.IO;
-
+ using System.Text;
using ImageSharp.PixelFormats;
///
@@ -30,17 +31,17 @@ namespace ImageSharp.Formats
///
///
///
- public class PngDecoder : IImageDecoder
+ public sealed class PngDecoder : IImageDecoder, IPngDecoderOptions
{
- ///
- public Image Decode(Configuration configuration, Stream stream, IDecoderOptions options)
-
- where TPixel : struct, IPixel
- {
- IPngDecoderOptions pngOptions = PngDecoderOptions.Create(options);
+ ///
+ /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
+ ///
+ public bool IgnoreMetadata { get; set; }
- return this.Decode(configuration, stream, pngOptions);
- }
+ ///
+ /// Gets or sets the encoding that should be used when reading text chunks.
+ ///
+ public Encoding TextEncoding { get; set; } = PngConstants.DefaultEncoding;
///
/// Decodes the image from the specified stream to the .
@@ -48,12 +49,12 @@ namespace ImageSharp.Formats
/// The pixel format.
/// The configuration for the image.
/// The containing image data.
- /// The options for the decoder.
/// The decoded image.
- public Image Decode(Configuration configuration, Stream stream, IPngDecoderOptions options)
+ public Image Decode(Configuration configuration, Stream stream)
where TPixel : struct, IPixel
{
- return new PngDecoderCore(options, configuration).Decode(stream);
+ var decoder = new PngDecoderCore(configuration, this);
+ return decoder.Decode(stream);
}
}
}
diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
index 2ff6a4308..e6f19b915 100644
--- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
@@ -11,7 +11,7 @@ namespace ImageSharp.Formats
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
-
+ using System.Text;
using ImageSharp.Memory;
using ImageSharp.PixelFormats;
@@ -20,7 +20,7 @@ namespace ImageSharp.Formats
///
/// Performs the png decoding operation.
///
- internal class PngDecoderCore
+ internal sealed class PngDecoderCore
{
///
/// The dictionary of available color types.
@@ -74,11 +74,6 @@ namespace ImageSharp.Formats
///
private readonly char[] chars = new char[4];
- ///
- /// The decoder options.
- ///
- private readonly IPngDecoderOptions options;
-
///
/// Reusable crc for validating chunks.
///
@@ -154,22 +149,33 @@ namespace ImageSharp.Formats
///
private int currentRowBytesRead;
+ ///
+ /// Gets or sets the png color type
+ ///
+ private PngColorType pngColorType;
+
+ ///
+ /// Gets the encoding to use
+ ///
+ private Encoding textEncoding;
+
+ ///
+ /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
+ ///
+ private bool ignoreMetadata;
+
///
/// Initializes a new instance of the class.
///
- /// The decoder options.
/// The configuration.
- public PngDecoderCore(IPngDecoderOptions options, Configuration configuration)
+ /// The decoder options.
+ public PngDecoderCore(Configuration configuration, IPngDecoderOptions options)
{
this.configuration = configuration ?? Configuration.Default;
- this.options = options ?? new PngDecoderOptions();
+ this.textEncoding = options.TextEncoding ?? PngConstants.DefaultEncoding;
+ this.ignoreMetadata = options.IgnoreMetadata;
}
- ///
- /// Gets or sets the png color type
- ///
- public PngColorType PngColorType { get; set; }
-
///
/// Decodes the stream to the image.
///
@@ -221,7 +227,6 @@ namespace ImageSharp.Formats
byte[] pal = new byte[currentChunk.Length];
Buffer.BlockCopy(currentChunk.Data, 0, pal, 0, currentChunk.Length);
this.palette = pal;
- metadata.Quality = pal.Length / 3;
break;
case PngChunkTypes.PaletteAlpha:
byte[] alpha = new byte[currentChunk.Length];
@@ -344,7 +349,7 @@ namespace ImageSharp.Formats
/// The
private int CalculateBytesPerPixel()
{
- switch (this.PngColorType)
+ switch (this.pngColorType)
{
case PngColorType.Grayscale:
return 1;
@@ -572,7 +577,7 @@ namespace ImageSharp.Formats
Span rowSpan = pixels.GetRowSpan(this.currentRow);
var scanlineBuffer = new Span(defilteredScanline, 1);
- switch (this.PngColorType)
+ switch (this.pngColorType)
{
case PngColorType.Grayscale:
int factor = 255 / ((int)Math.Pow(2, this.header.BitDepth) - 1);
@@ -731,7 +736,7 @@ namespace ImageSharp.Formats
{
var color = default(TPixel);
- switch (this.PngColorType)
+ switch (this.pngColorType)
{
case PngColorType.Grayscale:
int factor = 255 / ((int)Math.Pow(2, this.header.BitDepth) - 1);
@@ -896,7 +901,7 @@ namespace ImageSharp.Formats
/// The maximum length to read.
private void ReadTextChunk(ImageMetaData metadata, byte[] data, int length)
{
- if (this.options.IgnoreMetadata)
+ if (this.ignoreMetadata)
{
return;
}
@@ -912,8 +917,8 @@ namespace ImageSharp.Formats
}
}
- string name = this.options.TextEncoding.GetString(data, 0, zeroIndex);
- string value = this.options.TextEncoding.GetString(data, zeroIndex + 1, length - zeroIndex - 1);
+ string name = this.textEncoding.GetString(data, 0, zeroIndex);
+ string value = this.textEncoding.GetString(data, zeroIndex + 1, length - zeroIndex - 1);
metadata.Properties.Add(new ImageProperty(name, value));
}
@@ -967,7 +972,7 @@ namespace ImageSharp.Formats
throw new NotSupportedException("The png specification only defines 'None' and 'Adam7' as interlaced methods.");
}
- this.PngColorType = this.header.ColorType;
+ this.pngColorType = this.header.ColorType;
}
///
diff --git a/src/ImageSharp/Formats/Png/PngDecoderOptions.cs b/src/ImageSharp/Formats/Png/PngDecoderOptions.cs
deleted file mode 100644
index e8990ec45..000000000
--- a/src/ImageSharp/Formats/Png/PngDecoderOptions.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-//
-// Copyright (c) James Jackson-South and contributors.
-// Licensed under the Apache License, Version 2.0.
-//
-
-namespace ImageSharp.Formats
-{
- using System.Text;
-
- ///
- /// Encapsulates the options for the .
- ///
- public sealed class PngDecoderOptions : DecoderOptions, IPngDecoderOptions
- {
- private static readonly Encoding DefaultEncoding = Encoding.GetEncoding("ASCII");
-
- ///
- /// Initializes a new instance of the class.
- ///
- public PngDecoderOptions()
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The options for the decoder.
- private PngDecoderOptions(IDecoderOptions options)
- : base(options)
- {
- }
-
- ///
- /// Gets or sets the encoding that should be used when reading text chunks.
- ///
- public Encoding TextEncoding { get; set; } = DefaultEncoding;
-
- ///
- /// Converts the options to a instance with a cast
- /// or by creating a new instance with the specfied options.
- ///
- /// The options for the decoder.
- /// The options for the .
- internal static IPngDecoderOptions Create(IDecoderOptions options)
- {
- return options as IPngDecoderOptions ?? new PngDecoderOptions(options);
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Png/PngEncoder.cs b/src/ImageSharp/Formats/Png/PngEncoder.cs
index f89b624f7..bfd82a074 100644
--- a/src/ImageSharp/Formats/Png/PngEncoder.cs
+++ b/src/ImageSharp/Formats/Png/PngEncoder.cs
@@ -5,23 +5,61 @@
namespace ImageSharp.Formats
{
+ using System.Collections.Generic;
using System.IO;
using ImageSharp.PixelFormats;
+ using ImageSharp.Quantizers;
///
/// Image encoder for writing image data to a stream in png format.
///
- public class PngEncoder : IImageEncoder
+ public sealed class PngEncoder : IImageEncoder, IPngEncoderOptions
{
- ///
- public void Encode(Image image, Stream stream, IEncoderOptions options)
- where TPixel : struct, IPixel
- {
- IPngEncoderOptions pngOptions = PngEncoderOptions.Create(options);
+ ///
+ /// Gets or sets a value indicating whether the metadata should be ignored when the image is being encoded.
+ ///
+ public bool IgnoreMetadata { get; set; }
- this.Encode(image, stream, pngOptions);
- }
+ ///
+ /// Gets or sets the size of the color palette to use. Set to zero to leav png encoding to use pixel data.
+ ///
+ public int PaletteSize { get; set; } = 0;
+
+ ///
+ /// Gets or sets the png color type
+ ///
+ public PngColorType PngColorType { get; set; } = PngColorType.RgbWithAlpha;
+
+ ///
+ /// Gets or sets the compression level 1-9.
+ /// Defaults to 6.
+ ///
+ public int CompressionLevel { get; set; } = 6;
+
+ ///
+ /// Gets or sets the gamma value, that will be written
+ /// the the stream, when the property
+ /// is set to true. The default value is 2.2F.
+ ///
+ /// The gamma value of the image.
+ public float Gamma { get; set; } = 2.2F;
+
+ ///
+ /// Gets or sets quantizer for reducing the color count.
+ ///
+ public IQuantizer Quantizer { get; set; }
+
+ ///
+ /// Gets or sets the transparency threshold.
+ ///
+ public byte Threshold { get; set; } = 255;
+
+ ///
+ /// Gets or sets a value indicating whether this instance should write
+ /// gamma information to the stream. The default value is false.
+ ///
+ public bool WriteGamma { get; set; }
///
/// Encodes the image to the specified stream from the .
@@ -29,13 +67,12 @@ namespace ImageSharp.Formats
/// The pixel format.
/// The to encode from.
/// The to encode the image data to.
- /// The options for the encoder.
- public void Encode(Image image, Stream stream, IPngEncoderOptions options)
+ public void Encode(Image image, Stream stream)
where TPixel : struct, IPixel
{
- using (var encode = new PngEncoderCore(options))
+ using (var encoder = new PngEncoderCore(this))
{
- encode.Encode(image, stream);
+ encoder.Encode(image, stream);
}
}
}
diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
index 645df0548..cfbd0c449 100644
--- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
@@ -43,11 +43,6 @@ namespace ImageSharp.Formats
///
private readonly Crc32 crc = new Crc32();
- ///
- /// The options for the encoder.
- ///
- private readonly IPngEncoderOptions options;
-
///
/// Contains the raw pixel data from an indexed image.
///
@@ -113,11 +108,6 @@ namespace ImageSharp.Formats
///
private Buffer paeth;
- ///
- /// The quality of output for images.
- ///
- private int quality;
-
///
/// The png color type.
///
@@ -128,13 +118,50 @@ namespace ImageSharp.Formats
///
private IQuantizer quantizer;
+ ///
+ /// Gets or sets a value indicating whether to ignore metadata
+ ///
+ private bool ignoreMetadata;
+
+ ///
+ /// Gets or sets the Quality value
+ ///
+ private int paletteSize;
+
+ ///
+ /// Gets or sets the CompressionLevel value
+ ///
+ private int compressionLevel;
+
+ ///
+ /// Gets or sets the Gamma value
+ ///
+ private float gamma;
+
+ ///
+ /// Gets or sets the Threshold value
+ ///
+ private byte threshold;
+
+ ///
+ /// Gets or sets a value indicating whether to Write Gamma
+ ///
+ private bool writeGamma;
+
///
/// Initializes a new instance of the class.
///
- /// The options for the encoder.
+ /// The options for influancing the encoder
public PngEncoderCore(IPngEncoderOptions options)
{
- this.options = options ?? new PngEncoderOptions();
+ this.ignoreMetadata = options.IgnoreMetadata;
+ this.paletteSize = options.PaletteSize > 0 ? options.PaletteSize.Clamp(1, int.MaxValue) : int.MaxValue;
+ this.pngColorType = options.PngColorType;
+ this.compressionLevel = options.CompressionLevel;
+ this.gamma = options.Gamma;
+ this.quantizer = options.Quantizer;
+ this.threshold = options.Threshold;
+ this.writeGamma = options.WriteGamma;
}
///
@@ -164,27 +191,20 @@ namespace ImageSharp.Formats
stream.Write(this.chunkDataBuffer, 0, 8);
- // Ensure that quality can be set but has a fallback.
- this.quality = this.options.Quality > 0 ? this.options.Quality : image.MetaData.Quality;
- this.quality = this.quality > 0 ? this.quality.Clamp(1, int.MaxValue) : int.MaxValue;
-
- this.pngColorType = this.options.PngColorType;
- this.quantizer = this.options.Quantizer;
-
// Set correct color type if the color count is 256 or less.
- if (this.quality <= 256)
+ if (this.paletteSize <= 256)
{
this.pngColorType = PngColorType.Palette;
}
- if (this.pngColorType == PngColorType.Palette && this.quality > 256)
+ if (this.pngColorType == PngColorType.Palette && this.paletteSize > 256)
{
- this.quality = 256;
+ this.paletteSize = 256;
}
// Set correct bit depth.
- this.bitDepth = this.quality <= 256
- ? (byte)ImageMaths.GetBitsNeededForColorDepth(this.quality).Clamp(1, 8)
+ this.bitDepth = this.paletteSize <= 256
+ ? (byte)ImageMaths.GetBitsNeededForColorDepth(this.paletteSize).Clamp(1, 8)
: (byte)8;
// Png only supports in four pixel depths: 1, 2, 4, and 8 bits when using the PLTE chunk
@@ -514,7 +534,7 @@ namespace ImageSharp.Formats
private QuantizedImage WritePaletteChunk(Stream stream, PngHeader header, ImageBase image)
where TPixel : struct, IPixel
{
- if (this.quality > 256)
+ if (this.paletteSize > 256)
{
return null;
}
@@ -525,7 +545,7 @@ namespace ImageSharp.Formats
}
// Quantize the image returning a palette. This boxing is icky.
- QuantizedImage quantized = ((IQuantizer)this.quantizer).Quantize(image, this.quality);
+ QuantizedImage quantized = ((IQuantizer)this.quantizer).Quantize(image, this.paletteSize);
// Grab the palette and write it to the stream.
TPixel[] palette = quantized.Palette;
@@ -552,7 +572,7 @@ namespace ImageSharp.Formats
colorTable[offset + 1] = bytes[1];
colorTable[offset + 2] = bytes[2];
- if (alpha > this.options.Threshold)
+ if (alpha > this.threshold)
{
alpha = 255;
}
@@ -610,9 +630,9 @@ namespace ImageSharp.Formats
/// The containing image data.
private void WriteGammaChunk(Stream stream)
{
- if (this.options.WriteGamma)
+ if (this.writeGamma)
{
- int gammaValue = (int)(this.options.Gamma * 100000F);
+ int gammaValue = (int)(this.gamma * 100000F);
byte[] size = BitConverter.GetBytes(gammaValue);
@@ -655,7 +675,7 @@ namespace ImageSharp.Formats
try
{
memoryStream = new MemoryStream();
- using (var deflateStream = new ZlibDeflateStream(memoryStream, this.options.CompressionLevel))
+ using (var deflateStream = new ZlibDeflateStream(memoryStream, this.compressionLevel))
{
for (int y = 0; y < this.height; y++)
{
diff --git a/src/ImageSharp/Formats/Png/PngEncoderOptions.cs b/src/ImageSharp/Formats/Png/PngEncoderOptions.cs
deleted file mode 100644
index 90175c6d6..000000000
--- a/src/ImageSharp/Formats/Png/PngEncoderOptions.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-//
-// Copyright (c) James Jackson-South and contributors.
-// Licensed under the Apache License, Version 2.0.
-//
-
-namespace ImageSharp.Formats
-{
- using Quantizers;
-
- ///
- /// Encapsulates the options for the .
- ///
- public sealed class PngEncoderOptions : EncoderOptions, IPngEncoderOptions
- {
- ///
- /// Initializes a new instance of the class.
- ///
- public PngEncoderOptions()
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The options for the encoder.
- private PngEncoderOptions(IEncoderOptions options)
- : base(options)
- {
- }
-
- ///
- /// Gets or sets the quality of output for images.
- ///
- public int Quality { get; set; }
-
- ///
- /// Gets or sets the png color type
- ///
- public PngColorType PngColorType { get; set; } = PngColorType.RgbWithAlpha;
-
- ///
- /// Gets or sets the compression level 1-9.
- /// Defaults to 6.
- ///
- public int CompressionLevel { get; set; } = 6;
-
- ///
- /// Gets or sets the gamma value, that will be written
- /// the the stream, when the property
- /// is set to true. The default value is 2.2F.
- ///
- /// The gamma value of the image.
- public float Gamma { get; set; } = 2.2F;
-
- ///
- /// Gets or sets quantizer for reducing the color count.
- ///
- public IQuantizer Quantizer { get; set; }
-
- ///
- /// Gets or sets the transparency threshold.
- ///
- public byte Threshold { get; set; } = 255;
-
- ///
- /// Gets or sets a value indicating whether this instance should write
- /// gamma information to the stream. The default value is false.
- ///
- public bool WriteGamma { get; set; }
-
- ///
- /// Converts the options to a instance with a
- /// cast or by creating a new instance with the specfied options.
- ///
- /// The options for the encoder.
- /// The options for the .
- internal static IPngEncoderOptions Create(IEncoderOptions options)
- {
- return options as IPngEncoderOptions ?? new PngEncoderOptions(options);
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Png/PngFormat.cs b/src/ImageSharp/Formats/Png/PngFormat.cs
index 0f5a74da0..551b4a8c7 100644
--- a/src/ImageSharp/Formats/Png/PngFormat.cs
+++ b/src/ImageSharp/Formats/Png/PngFormat.cs
@@ -8,40 +8,20 @@ namespace ImageSharp.Formats
using System.Collections.Generic;
///
- /// Encapsulates the means to encode and decode png images.
+ /// Registers the image encoders, decoders and mime type detectors for the jpeg format.
///
- public class PngFormat : IImageFormat
+ internal sealed class PngFormat : IImageFormat
{
///
- public string MimeType => "image/png";
+ public string Name => "PNG";
///
- public string Extension => "png";
+ public string DefaultMimeType => "image/png";
///
- public IEnumerable SupportedExtensions => new string[] { "png" };
+ public IEnumerable MimeTypes => PngConstants.MimeTypes;
///
- public IImageDecoder Decoder => new PngDecoder();
-
- ///
- public IImageEncoder Encoder => new PngEncoder();
-
- ///
- public int HeaderSize => 8;
-
- ///
- public bool IsSupportedFileFormat(byte[] header)
- {
- return header.Length >= this.HeaderSize &&
- header[0] == 0x89 &&
- header[1] == 0x50 && // P
- header[2] == 0x4E && // N
- header[3] == 0x47 && // G
- header[4] == 0x0D && // CR
- header[5] == 0x0A && // LF
- header[6] == 0x1A && // EOF
- header[7] == 0x0A; // LF
- }
+ public IEnumerable FileExtensions => PngConstants.FileExtensions;
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Png/PngHeader.cs b/src/ImageSharp/Formats/Png/PngHeader.cs
index 50d6cc9ec..9cf823fa1 100644
--- a/src/ImageSharp/Formats/Png/PngHeader.cs
+++ b/src/ImageSharp/Formats/Png/PngHeader.cs
@@ -8,7 +8,7 @@ namespace ImageSharp.Formats
///
/// Represents the png header chunk.
///
- public sealed class PngHeader
+ internal sealed class PngHeader
{
///
/// Gets or sets the dimension in x-direction of the image in pixels.
diff --git a/src/ImageSharp/Formats/Png/PngImageFormatDetector.cs b/src/ImageSharp/Formats/Png/PngImageFormatDetector.cs
new file mode 100644
index 000000000..fdea3eb8a
--- /dev/null
+++ b/src/ImageSharp/Formats/Png/PngImageFormatDetector.cs
@@ -0,0 +1,43 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Formats
+{
+ using System;
+
+ ///
+ /// Detects png file headers
+ ///
+ public sealed class PngImageFormatDetector : IImageFormatDetector
+ {
+ ///
+ public int HeaderSize => 8;
+
+ ///
+ public IImageFormat DetectFormat(ReadOnlySpan header)
+ {
+ if (this.IsSupportedFileFormat(header))
+ {
+ return ImageFormats.Png;
+ }
+
+ return null;
+ }
+
+ private bool IsSupportedFileFormat(ReadOnlySpan header)
+ {
+ // TODO: This should be in constants
+ return header.Length >= this.HeaderSize &&
+ header[0] == 0x89 &&
+ header[1] == 0x50 && // P
+ header[2] == 0x4E && // N
+ header[3] == 0x47 && // G
+ header[4] == 0x0D && // CR
+ header[5] == 0x0A && // LF
+ header[6] == 0x1A && // EOF
+ header[7] == 0x0A; // LF
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Png/PngInterlaceMode.cs b/src/ImageSharp/Formats/Png/PngInterlaceMode.cs
index ec3b8ebe7..b43aff0b7 100644
--- a/src/ImageSharp/Formats/Png/PngInterlaceMode.cs
+++ b/src/ImageSharp/Formats/Png/PngInterlaceMode.cs
@@ -8,7 +8,7 @@ namespace ImageSharp.Formats
///
/// Provides enumeration of available PNG interlace modes.
///
- public enum PngInterlaceMode : byte
+ internal enum PngInterlaceMode : byte
{
///
/// Non interlaced
diff --git a/src/ImageSharp/Formats/Png/Zlib/IChecksum.cs b/src/ImageSharp/Formats/Png/Zlib/IChecksum.cs
index 935cdf953..cbd292dc4 100644
--- a/src/ImageSharp/Formats/Png/Zlib/IChecksum.cs
+++ b/src/ImageSharp/Formats/Png/Zlib/IChecksum.cs
@@ -12,7 +12,7 @@ namespace ImageSharp.Formats
/// Value. The complete checksum object can also be reset
/// so it can be used again with new data.
///
- public interface IChecksum
+ internal interface IChecksum
{
///
/// Gets the data checksum computed so far.
diff --git a/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs b/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs
index 0743d8ded..136f919da 100644
--- a/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs
+++ b/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs
@@ -9,7 +9,7 @@
///
/// Provides methods and properties for deframing streams from PNGs.
///
- internal class ZlibInflateStream : Stream
+ internal sealed class ZlibInflateStream : Stream
{
///
/// The inner raw memory stream
diff --git a/src/ImageSharp/IConfigurationModule.cs b/src/ImageSharp/IConfigurationModule.cs
new file mode 100644
index 000000000..95b92ed05
--- /dev/null
+++ b/src/ImageSharp/IConfigurationModule.cs
@@ -0,0 +1,19 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp
+{
+ ///
+ /// Represents an interface that can register image encoders, decoders and image format detectors.
+ ///
+ public interface IConfigurationModule
+ {
+ ///
+ /// Called when loaded into a configuration object so the module can register items into the configuration.
+ ///
+ /// The configuration that will retain the encoders, decodes and mime type detectors.
+ void Configure(Configuration configuration);
+ }
+}
diff --git a/src/ImageSharp/Image/IImage.cs b/src/ImageSharp/Image/IImage.cs
index 55abdb244..b9e8e392a 100644
--- a/src/ImageSharp/Image/IImage.cs
+++ b/src/ImageSharp/Image/IImage.cs
@@ -12,11 +12,6 @@ namespace ImageSharp
///
internal interface IImage : IImageBase
{
- ///
- /// Gets the currently loaded image format.
- ///
- IImageFormat CurrentImageFormat { get; }
-
///
/// Gets the meta data of the image.
///
diff --git a/src/ImageSharp/Image/Image.Decode.cs b/src/ImageSharp/Image/Image.Decode.cs
index c162f1772..101310706 100644
--- a/src/ImageSharp/Image/Image.Decode.cs
+++ b/src/ImageSharp/Image/Image.Decode.cs
@@ -5,11 +5,10 @@
namespace ImageSharp
{
- using System.Buffers;
using System.IO;
using System.Linq;
using Formats;
-
+ using ImageSharp.Memory;
using ImageSharp.PixelFormats;
///
@@ -22,8 +21,8 @@ namespace ImageSharp
///
/// The image stream to read the header from.
/// The configuration.
- /// The image format or null if none found.
- private static IImageFormat DiscoverFormat(Stream stream, Configuration config)
+ /// The mime type or null if none found.
+ private static IImageFormat InternalDetectFormat(Stream stream, Configuration config)
{
// This is probably a candidate for making into a public API in the future!
int maxHeaderSize = config.MaxHeaderSize;
@@ -32,45 +31,55 @@ namespace ImageSharp
return null;
}
- IImageFormat format;
- byte[] header = ArrayPool.Shared.Rent(maxHeaderSize);
- try
+ using (var buffer = new Buffer(maxHeaderSize))
{
long startPosition = stream.Position;
- stream.Read(header, 0, maxHeaderSize);
+ stream.Read(buffer.Array, 0, maxHeaderSize);
stream.Position = startPosition;
- format = config.ImageFormats.FirstOrDefault(x => x.IsSupportedFileFormat(header));
+ return config.FormatDetectors.Select(x => x.DetectFormat(buffer)).LastOrDefault(x => x != null);
}
- finally
+ }
+
+ ///
+ /// By reading the header on the provided stream this calculates the images format.
+ ///
+ /// The image stream to read the header from.
+ /// The configuration.
+ /// The IImageFormat.
+ /// The image format or null if none found.
+ private static IImageDecoder DiscoverDecoder(Stream stream, Configuration config, out IImageFormat format)
+ {
+ format = InternalDetectFormat(stream, config);
+ if (format != null)
{
- ArrayPool.Shared.Return(header);
+ return config.FindDecoder(format);
}
- return format;
+ return null;
}
+#pragma warning disable SA1008 // Opening parenthesis must be spaced correctly
///
/// Decodes the image stream to the current image.
///
/// The stream.
- /// The options for the decoder.
/// the configuration.
/// The pixel format.
///
/// A new .
///
- private static Image Decode(Stream stream, IDecoderOptions options, Configuration config)
+ private static (Image img, IImageFormat format) Decode(Stream stream, Configuration config)
+#pragma warning restore SA1008 // Opening parenthesis must be spaced correctly
where TPixel : struct, IPixel
{
- IImageFormat format = DiscoverFormat(stream, config);
- if (format == null)
+ IImageDecoder decoder = DiscoverDecoder(stream, config, out IImageFormat format);
+ if (decoder == null)
{
- return null;
+ return (null, null);
}
- Image img = format.Decoder.Decode(config, stream, options);
- img.CurrentImageFormat = format;
- return img;
+ Image img = decoder.Decode(config, stream);
+ return (img, format);
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Image/Image.FromBytes.cs b/src/ImageSharp/Image/Image.FromBytes.cs
index 628092359..c7023b860 100644
--- a/src/ImageSharp/Image/Image.FromBytes.cs
+++ b/src/ImageSharp/Image/Image.FromBytes.cs
@@ -15,54 +15,78 @@ namespace ImageSharp
///
public static partial class Image
{
+ ///
+ /// By reading the header on the provided byte array this calculates the images format.
+ ///
+ /// The byte array containing image data to read the header from.
+ /// The format or null if none found.
+ public static IImageFormat DetectFormat(byte[] data)
+ {
+ return DetectFormat(null, data);
+ }
+
+ ///
+ /// By reading the header on the provided byte array this calculates the images format.
+ ///
+ /// The configuration.
+ /// The byte array containing image data to read the header from.
+ /// The mime type or null if none found.
+ public static IImageFormat DetectFormat(Configuration config, byte[] data)
+ {
+ using (Stream stream = new MemoryStream(data))
+ {
+ return DetectFormat(config, stream);
+ }
+ }
+
///
/// Create a new instance of the class from the given byte array.
///
/// The byte array containing image data.
/// A new .
- public static Image Load(byte[] data) => Load(null, data, null);
+ public static Image Load(byte[] data) => Load(null, data);
///
/// Create a new instance of the class from the given byte array.
///
/// The byte array containing image data.
- /// The options for the decoder.
+ /// The mime type of the decoded image.
/// A new .
- public static Image Load(byte[] data, IDecoderOptions options) => Load(null, data, options);
+ public static Image Load(byte[] data, out IImageFormat format) => Load(null, data, out format);
///
- /// Create a new instance of the class from the given byte array.
+ /// Create a new instance of the class from the given byte array.
///
/// The config for the decoder.
/// The byte array containing image data.
/// A new .
- public static Image Load(Configuration config, byte[] data) => Load(config, data, null);
+ public static Image Load(Configuration config, byte[] data) => Load(config, data);
///
/// Create a new instance of the class from the given byte array.
///
+ /// The config for the decoder.
/// The byte array containing image data.
- /// The decoder.
+ /// The mime type of the decoded image.
/// A new .
- public static Image Load(byte[] data, IImageDecoder decoder) => Load(data, decoder, null);
+ public static Image Load(Configuration config, byte[] data, out IImageFormat format) => Load(config, data, out format);
///
- /// Create a new instance of the class from the given byte array.
+ /// Create a new instance of the class from the given byte array.
///
- /// The configuration options.
/// The byte array containing image data.
- /// The options for the decoder.
+ /// The decoder.
/// A new .
- public static Image Load(Configuration config, byte[] data, IDecoderOptions options) => Load(config, data, options);
+ public static Image Load(byte[] data, IImageDecoder decoder) => Load(data, decoder);
///
- /// Create a new instance of the class from the given byte array.
+ /// Create a new instance of the class from the given byte array.
///
+ /// The config for the decoder.
/// The byte array containing image data.
/// The decoder.
- /// The options for the decoder.
/// A new .
- public static Image Load(byte[] data, IImageDecoder decoder, IDecoderOptions options) => Load(data, decoder, options);
+ public static Image Load(Configuration config, byte[] data, IImageDecoder decoder) => Load(config, data, decoder);
///
/// Create a new instance of the class from the given byte array.
@@ -73,79 +97,85 @@ namespace ImageSharp
public static Image Load(byte[] data)
where TPixel : struct, IPixel
{
- return Load(null, data, null);
+ return Load(null, data);
}
///
/// Create a new instance of the class from the given byte array.
///
/// The byte array containing image data.
- /// The options for the decoder.
+ /// The mime type of the decoded image.
/// The pixel format.
/// A new .
- public static Image Load(byte[] data, IDecoderOptions options)
+ public static Image Load(byte[] data, out IImageFormat format)
where TPixel : struct, IPixel
{
- return Load(null, data, options);
+ return Load(null, data, out format);
}
///
/// Create a new instance of the class from the given byte array.
///
- /// The config for the decoder.
+ /// The configuration options.
/// The byte array containing image data.
/// The pixel format.
/// A new .
public static Image Load(Configuration config, byte[] data)
where TPixel : struct, IPixel
{
- return Load(config, data, null);
+ using (var memoryStream = new MemoryStream(data))
+ {
+ return Load(config, memoryStream);
+ }
}
///
/// Create a new instance of the class from the given byte array.
///
+ /// The configuration options.
/// The byte array containing image data.
- /// The decoder.
+ /// The mime type of the decoded image.
/// The pixel format.
/// A new .
- public static Image Load(byte[] data, IImageDecoder decoder)
+ public static Image Load(Configuration config, byte[] data, out IImageFormat format)
where TPixel : struct, IPixel
{
- return Load(data, decoder, null);
+ using (var memoryStream = new MemoryStream(data))
+ {
+ return Load(config, memoryStream, out format);
+ }
}
///
/// Create a new instance of the class from the given byte array.
///
- /// The configuration options.
/// The byte array containing image data.
- /// The options for the decoder.
+ /// The decoder.
/// The pixel format.
/// A new .
- public static Image Load(Configuration config, byte[] data, IDecoderOptions options)
+ public static Image Load(byte[] data, IImageDecoder decoder)
where TPixel : struct, IPixel
{
- using (var ms = new MemoryStream(data))
+ using (var memoryStream = new MemoryStream(data))
{
- return Load(config, ms, options);
+ return Load(memoryStream, decoder);
}
}
///
/// Create a new instance of the class from the given byte array.
///
+ /// The Configuration.
/// The byte array containing image data.
/// The decoder.
- /// The options for the decoder.
/// The pixel format.
/// A new .
- public static Image Load(byte[] data, IImageDecoder decoder, IDecoderOptions options)
+ public static Image Load(Configuration config, byte[] data, IImageDecoder decoder)
where TPixel : struct, IPixel
{
- using (var ms = new MemoryStream(data))
+ using (var memoryStream = new MemoryStream(data))
{
- return Load(ms, decoder, options);
+ return Load(config, memoryStream, decoder);
}
}
}
diff --git a/src/ImageSharp/Image/Image.FromFile.cs b/src/ImageSharp/Image/Image.FromFile.cs
index a135c43f5..ca395ce08 100644
--- a/src/ImageSharp/Image/Image.FromFile.cs
+++ b/src/ImageSharp/Image/Image.FromFile.cs
@@ -16,6 +16,31 @@ namespace ImageSharp
///
public static partial class Image
{
+ ///
+ /// By reading the header on the provided file this calculates the images mime type.
+ ///
+ /// The image file to open and to read the header from.
+ /// The mime type or null if none found.
+ public static IImageFormat DetectFormat(string filePath)
+ {
+ return DetectFormat(null, filePath);
+ }
+
+ ///
+ /// By reading the header on the provided file this calculates the images mime type.
+ ///
+ /// The configuration.
+ /// The image file to open and to read the header from.
+ /// The mime type or null if none found.
+ public static IImageFormat DetectFormat(Configuration config, string filePath)
+ {
+ config = config ?? Configuration.Default;
+ using (Stream file = config.FileSystem.OpenRead(filePath))
+ {
+ return DetectFormat(config, file);
+ }
+ }
+
///
/// Create a new instance of the class from the given file.
///
@@ -30,12 +55,12 @@ namespace ImageSharp
/// Create a new instance of the class from the given file.
///
/// The file path to the image.
- /// The options for the decoder.
+ /// The mime type of the decoded image.
///
/// Thrown if the stream is not readable nor seekable.
///
- /// A new .
- public static Image Load(string path, IDecoderOptions options) => Load(path, options);
+ /// A new .
+ public static Image Load(string path, out IImageFormat format) => Load(path, out format);
///
/// Create a new instance of the class from the given file.
@@ -51,37 +76,37 @@ namespace ImageSharp
///
/// Create a new instance of the class from the given file.
///
+ /// The config for the decoder.
/// The file path to the image.
- /// The decoder.
+ /// The mime type of the decoded image.
///
/// Thrown if the stream is not readable nor seekable.
///
/// A new .
- public static Image Load(string path, IImageDecoder decoder) => Load(path, decoder);
+ public static Image Load(Configuration config, string path, out IImageFormat format) => Load(config, path, out format);
///
/// Create a new instance of the class from the given file.
///
- /// The configuration options.
+ /// The Configuration.
/// The file path to the image.
- /// The options for the decoder.
+ /// The decoder.
///
/// Thrown if the stream is not readable nor seekable.
///
/// A new .
- public static Image Load(Configuration config, string path, IDecoderOptions options) => Load(config, path, options);
+ public static Image Load(Configuration config, string path, IImageDecoder decoder) => Load(config, path, decoder);
///
/// Create a new instance of the class from the given file.
///
/// The file path to the image.
/// The decoder.
- /// The options for the decoder.
///
/// Thrown if the stream is not readable nor seekable.
///
/// A new .
- public static Image Load(string path, IImageDecoder decoder, IDecoderOptions options) => Load(path, decoder, options);
+ public static Image Load(string path, IImageDecoder decoder) => Load(path, decoder);
///
/// Create a new instance of the class from the given file.
@@ -95,29 +120,29 @@ namespace ImageSharp
public static Image Load(string path)
where TPixel : struct, IPixel
{
- return Load(null, path, null);
+ return Load(null, path);
}
///
/// Create a new instance of the class from the given file.
///
/// The file path to the image.
- /// The options for the decoder.
+ /// The mime type of the decoded image.
///
/// Thrown if the stream is not readable nor seekable.
///
/// The pixel format.
/// A new .
- public static Image Load(string path, IDecoderOptions options)
+ public static Image Load(string path, out IImageFormat format)
where TPixel : struct, IPixel
{
- return Load(null, path, options);
+ return Load(null, path, out format);
}
///
/// Create a new instance of the class from the given file.
///
- /// The config for the decoder.
+ /// The configuration options.
/// The file path to the image.
///
/// Thrown if the stream is not readable nor seekable.
@@ -127,64 +152,68 @@ namespace ImageSharp
public static Image Load(Configuration config, string path)
where TPixel : struct, IPixel
{
- return Load(config, path, null);
+ config = config ?? Configuration.Default;
+ using (Stream stream = config.FileSystem.OpenRead(path))
+ {
+ return Load(config, stream);
+ }
}
///
/// Create a new instance of the class from the given file.
///
+ /// The configuration options.
/// The file path to the image.
- /// The decoder.
+ /// The mime type of the decoded image.
///
/// Thrown if the stream is not readable nor seekable.
///
/// The pixel format.
/// A new .
- public static Image Load(string path, IImageDecoder decoder)
+ public static Image Load(Configuration config, string path, out IImageFormat format)
where TPixel : struct, IPixel
{
- return Load(path, decoder, null);
+ config = config ?? Configuration.Default;
+ using (Stream stream = config.FileSystem.OpenRead(path))
+ {
+ return Load(config, stream, out format);
+ }
}
///
/// Create a new instance of the class from the given file.
///
- /// The configuration options.
/// The file path to the image.
- /// The options for the decoder.
+ /// The decoder.
///
/// Thrown if the stream is not readable nor seekable.
///
/// The pixel format.
/// A new .
- public static Image Load(Configuration config, string path, IDecoderOptions options)
+ public static Image Load(string path, IImageDecoder decoder)
where TPixel : struct, IPixel
{
- config = config ?? Configuration.Default;
- using (Stream s = config.FileSystem.OpenRead(path))
- {
- return Load(config, s, options);
- }
+ return Load(null, path, decoder);
}
///
/// Create a new instance of the class from the given file.
///
+ /// The Configuration.
/// The file path to the image.
/// The decoder.
- /// The options for the decoder.
///
/// Thrown if the stream is not readable nor seekable.
///
/// The pixel format.
/// A new .
- public static Image Load(string path, IImageDecoder decoder, IDecoderOptions options)
+ public static Image Load(Configuration config, string path, IImageDecoder decoder)
where TPixel : struct, IPixel
{
- Configuration config = Configuration.Default;
- using (Stream s = config.FileSystem.OpenRead(path))
+ config = config ?? Configuration.Default;
+ using (Stream stream = config.FileSystem.OpenRead(path))
{
- return Load(s, decoder, options);
+ return Load(config, stream, decoder);
}
}
}
diff --git a/src/ImageSharp/Image/Image.FromStream.cs b/src/ImageSharp/Image/Image.FromStream.cs
index 1bcb5adc9..29d93ae85 100644
--- a/src/ImageSharp/Image/Image.FromStream.cs
+++ b/src/ImageSharp/Image/Image.FromStream.cs
@@ -6,6 +6,7 @@
namespace ImageSharp
{
using System;
+ using System.Collections.Generic;
using System.IO;
using System.Text;
using Formats;
@@ -17,26 +18,47 @@ namespace ImageSharp
///
public static partial class Image
{
+ ///
+ /// By reading the header on the provided stream this calculates the images mime type.
+ ///
+ /// The image stream to read the header from.
+ /// The mime type or null if none found.
+ public static IImageFormat DetectFormat(Stream stream)
+ {
+ return DetectFormat(null, stream);
+ }
+
+ ///
+ /// By reading the header on the provided stream this calculates the images mime type.
+ ///
+ /// The configuration.
+ /// The image stream to read the header from.
+ /// The mime type or null if none found.
+ public static IImageFormat DetectFormat(Configuration config, Stream stream)
+ {
+ return WithSeekableStream(stream, s => InternalDetectFormat(s, config ?? Configuration.Default));
+ }
+
///
/// Create a new instance of the class from the given stream.
///
/// The stream containing image information.
+ /// the mime type of the decoded image.
///
/// Thrown if the stream is not readable nor seekable.
///
/// A new .>
- public static Image Load(Stream stream) => Load(stream);
+ public static Image Load(Stream stream, out IImageFormat format) => Load(stream, out format);
///
/// Create a new instance of the class from the given stream.
///
/// The stream containing image information.
- /// The options for the decoder.
///
/// Thrown if the stream is not readable nor seekable.
///
/// A new .>
- public static Image Load(Stream stream, IDecoderOptions options) => Load(stream, options);
+ public static Image Load(Stream stream) => Load(stream);
///
/// Create a new instance of the class from the given stream.
@@ -63,14 +85,14 @@ namespace ImageSharp
///
/// Create a new instance of the class from the given stream.
///
+ /// The config for the decoder.
/// The stream containing image information.
- /// The decoder.
- /// The options for the decoder.
+ /// the mime type of the decoded image.
///
/// Thrown if the stream is not readable nor seekable.
///
- /// A new .>
- public static Image Load(Stream stream, IImageDecoder decoder, IDecoderOptions options) => Load(stream, decoder, options);
+ /// A new .>
+ public static Image Load(Configuration config, Stream stream, out IImageFormat format) => Load(config, stream, out format);
///
/// Create a new instance of the class from the given stream.
@@ -84,44 +106,45 @@ namespace ImageSharp
public static Image Load(Stream stream)
where TPixel : struct, IPixel
{
- return Load(null, stream, null);
+ return Load(null, stream);
}
///
/// Create a new instance of the class from the given stream.
///
/// The stream containing image information.
- /// The options for the decoder.
+ /// the mime type of the decoded image.
///
/// Thrown if the stream is not readable nor seekable.
///
/// The pixel format.
/// A new .>
- public static Image Load(Stream stream, IDecoderOptions options)
+ public static Image Load(Stream stream, out IImageFormat format)
where TPixel : struct, IPixel
{
- return Load(null, stream, options);
+ return Load(null, stream, out format);
}
///
/// Create a new instance of the class from the given stream.
///
- /// The config for the decoder.
/// The stream containing image information.
+ /// The decoder.
///
/// Thrown if the stream is not readable nor seekable.
///
/// The pixel format.
/// A new .>
- public static Image Load(Configuration config, Stream stream)
+ public static Image Load(Stream stream, IImageDecoder decoder)
where TPixel : struct, IPixel
{
- return Load(config, stream, null);
+ return WithSeekableStream(stream, s => decoder.Decode(Configuration.Default, s));
}
///
/// Create a new instance of the class from the given stream.
///
+ /// The Configuration.
/// The stream containing image information.
/// The decoder.
///
@@ -129,27 +152,26 @@ namespace ImageSharp
///
/// The pixel format.
/// A new .>
- public static Image Load(Stream stream, IImageDecoder decoder)
+ public static Image Load(Configuration config, Stream stream, IImageDecoder decoder)
where TPixel : struct, IPixel
{
- return Load(stream, decoder, null);
+ return WithSeekableStream(stream, s => decoder.Decode(config, s));
}
///
/// Create a new instance of the class from the given stream.
///
+ /// The configuration options.
/// The stream containing image information.
- /// The decoder.
- /// The options for the decoder.
///
/// Thrown if the stream is not readable nor seekable.
///
/// The pixel format.
/// A new .>
- public static Image Load(Stream stream, IImageDecoder decoder, IDecoderOptions options)
+ public static Image Load(Configuration config, Stream stream)
where TPixel : struct, IPixel
{
- return WithSeekableStream(stream, s => decoder.Decode(Configuration.Default, s, options));
+ return Load(config, stream, out var _);
}
///
@@ -157,29 +179,31 @@ namespace ImageSharp
///
/// The configuration options.
/// The stream containing image information.
- /// The options for the decoder.
+ /// the mime type of the decoded image.
///
/// Thrown if the stream is not readable nor seekable.
///
/// The pixel format.
/// A new .>
- public static Image Load(Configuration config, Stream stream, IDecoderOptions options)
- where TPixel : struct, IPixel
+ public static Image Load(Configuration config, Stream stream, out IImageFormat format)
+ where TPixel : struct, IPixel
{
config = config ?? Configuration.Default;
- Image img = WithSeekableStream(stream, s => Decode(s, options, config));
+ (Image img, IImageFormat format) data = WithSeekableStream(stream, s => Decode(s, config));
+
+ format = data.format;
- if (img != null)
+ if (data.img != null)
{
- return img;
+ return data.img;
}
- StringBuilder stringBuilder = new StringBuilder();
- stringBuilder.AppendLine("Image cannot be loaded. Available formats:");
+ var stringBuilder = new StringBuilder();
+ stringBuilder.AppendLine("Image cannot be loaded. Available decoders:");
- foreach (IImageFormat format in config.ImageFormats)
+ foreach (KeyValuePair val in config.ImageDecoders)
{
- stringBuilder.AppendLine("-" + format);
+ stringBuilder.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}");
}
throw new NotSupportedException(stringBuilder.ToString());
@@ -198,12 +222,12 @@ namespace ImageSharp
}
// We want to be able to load images from things like HttpContext.Request.Body
- using (MemoryStream ms = new MemoryStream())
+ using (var memoryStream = new MemoryStream())
{
- stream.CopyTo(ms);
- ms.Position = 0;
+ stream.CopyTo(memoryStream);
+ memoryStream.Position = 0;
- return action(ms);
+ return action(memoryStream);
}
}
}
diff --git a/src/ImageSharp/Image/Image{TPixel}.cs b/src/ImageSharp/Image/Image{TPixel}.cs
index 1cda8ebc7..5e8bcab31 100644
--- a/src/ImageSharp/Image/Image{TPixel}.cs
+++ b/src/ImageSharp/Image/Image{TPixel}.cs
@@ -9,8 +9,8 @@ namespace ImageSharp
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
- using System.Linq;
using System.Numerics;
+ using System.Text;
using System.Threading.Tasks;
using Formats;
@@ -95,13 +95,7 @@ namespace ImageSharp
internal Image(Configuration configuration, int width, int height, ImageMetaData metadata)
: base(configuration, width, height)
{
- if (!this.Configuration.ImageFormats.Any())
- {
- throw new InvalidOperationException("No image formats have been configured.");
- }
-
this.MetaData = metadata ?? new ImageMetaData();
- this.CurrentImageFormat = this.Configuration.ImageFormats.First();
}
///
@@ -139,11 +133,6 @@ namespace ImageSharp
/// The list of frame images.
public IList> Frames { get; } = new List>();
- ///
- /// Gets the currently loaded image format.
- ///
- public IImageFormat CurrentImageFormat { get; internal set; }
-
///
/// Applies the processor to the image.
///
@@ -163,48 +152,28 @@ namespace ImageSharp
/// Saves the image to the given stream using the currently loaded image format.
///
/// The stream to save the image to.
+ /// The format to save the image to.
/// Thrown if the stream is null.
/// The
- public Image Save(Stream stream)
+ public Image Save(Stream stream, IImageFormat format)
{
- return this.Save(stream, (IEncoderOptions)null);
- }
+ Guard.NotNull(format, nameof(format));
+ IImageEncoder encoder = this.Configuration.FindEncoder(format);
- ///
- /// Saves the image to the given stream using the currently loaded image format.
- ///
- /// The stream to save the image to.
- /// The options for the encoder.
- /// Thrown if the stream is null.
- /// The
- public Image Save(Stream stream, IEncoderOptions options)
- {
- return this.Save(stream, this.CurrentImageFormat?.Encoder, options);
- }
+ if (encoder == null)
+ {
+ var stringBuilder = new StringBuilder();
+ stringBuilder.AppendLine("Can't find encoder for provided mime type. Available encoded:");
- ///
- /// Saves the image to the given stream using the given image format.
- ///
- /// The stream to save the image to.
- /// The format to save the image as.
- /// The
- public Image Save(Stream stream, IImageFormat format)
- {
- return this.Save(stream, format, null);
- }
+ foreach (KeyValuePair val in this.Configuration.ImageEncoders)
+ {
+ stringBuilder.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}");
+ }
- ///
- /// Saves the image to the given stream using the given image format.
- ///
- /// The stream to save the image to.
- /// The format to save the image as.
- /// The options for the encoder.
- /// The
- public Image Save(Stream stream, IImageFormat format, IEncoderOptions options)
- {
- Guard.NotNull(format, nameof(format));
+ throw new NotSupportedException(stringBuilder.ToString());
+ }
- return this.Save(stream, format.Encoder, options);
+ return this.Save(stream, encoder);
}
///
@@ -217,26 +186,11 @@ namespace ImageSharp
/// The .
///
public Image Save(Stream stream, IImageEncoder encoder)
- {
- return this.Save(stream, encoder, null);
- }
-
- ///
- /// Saves the image to the given stream using the given image encoder.
- ///
- /// The stream to save the image to.
- /// The encoder to save the image with.
- /// The options for the encoder.
- /// Thrown if the stream or encoder is null.
- ///
- /// The .
- ///
- public Image Save(Stream stream, IImageEncoder encoder, IEncoderOptions options)
{
Guard.NotNull(stream, nameof(stream));
Guard.NotNull(encoder, nameof(encoder));
- encoder.Encode(this, stream, options);
+ encoder.Encode(this, stream);
return this;
}
@@ -250,64 +204,37 @@ namespace ImageSharp
/// The
public Image Save(string filePath)
{
- return this.Save(filePath, (IEncoderOptions)null);
- }
+ Guard.NotNullOrEmpty(filePath, nameof(filePath));
- ///
- /// Saves the image to the given stream using the currently loaded image format.
- ///
- /// The file path to save the image to.
- /// The options for the encoder.
- /// Thrown if the stream is null.
- /// The