diff --git a/src/ImageSharp/Configuration.cs b/src/ImageSharp/Configuration.cs
index fa983d355..5734d70fb 100644
--- a/src/ImageSharp/Configuration.cs
+++ b/src/ImageSharp/Configuration.cs
@@ -30,27 +30,20 @@ namespace ImageSharp
private readonly object syncRoot = new object();
///
- /// The list of supported .
+ /// The list of supported .
///
- private readonly List imageFormatsList = new List();
+ private readonly List encoders = new List();
///
- /// Initializes a new instance of the class.
+ /// The list of supported .
///
- public Configuration()
- {
- }
+ private readonly List decoders = new List();
///
/// Initializes a new instance of the class.
///
- /// The inital set of image formats.
- public Configuration(params IImageFormat[] providers)
+ public Configuration()
{
- foreach (IImageFormat p in providers)
- {
- this.AddImageFormat(p);
- }
}
///
@@ -59,9 +52,14 @@ namespace ImageSharp
public static Configuration Default { get; } = Lazy.Value;
///
- /// Gets the collection of supported
+ /// Gets the collection of supported
///
- public IReadOnlyCollection ImageFormats => new ReadOnlyCollection(this.imageFormatsList);
+ public IReadOnlyCollection ImageEncoders => new ReadOnlyCollection(this.encoders);
+
+ ///
+ /// Gets the collection of supported
+ ///
+ public IReadOnlyCollection ImageDecoders => new ReadOnlyCollection(this.decoders);
///
/// Gets the global parallel options for processing tasks in parallel.
@@ -81,118 +79,57 @@ namespace ImageSharp
#endif
///
- /// Adds a new to the collection of supported image formats.
- ///
- /// The new format to add.
- 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.");
-
- this.AddImageFormatLocked(format);
- }
-
- ///
- /// Creates the default instance, with Png, Jpeg, Gif and Bmp preregisterd (if they have been referenced)
+ /// Adds a new to the collection of supported image formats.
///
- /// The default configuration of
- internal static Configuration CreateDefaultInstance()
+ /// The new format to add.
+ public void AddImageFormat(IImageDecoder decoder)
{
- 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;
- }
+ Guard.NotNull(decoder, nameof(decoder));
+ Guard.NotNullOrEmpty(decoder.FileExtensions, nameof(decoder.FileExtensions));
+ Guard.NotNullOrEmpty(decoder.MimeTypes, nameof(decoder.MimeTypes));
- ///
- /// Tries the add image format.
- ///
- /// Name of the type.
- /// True if type discoverd and is a valid
- internal bool TryAddImageFormat(string typeName)
- {
- Type type = Type.GetType(typeName, false);
- if (type != null)
+ lock (this.syncRoot)
{
- 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;
- }
- }
+ this.decoders.Add(decoder);
- return false;
+ this.SetMaxHeaderSize();
+ }
}
///
- /// Adds image format. The class is locked to make it thread safe.
+ /// Adds a new to the collection of supported image formats.
///
- /// The image format.
- private void AddImageFormatLocked(IImageFormat format)
+ /// The new format to add.
+ public void AddImageFormat(IImageEncoder encoder)
{
+ Guard.NotNull(encoder, nameof(encoder));
+ Guard.NotNullOrEmpty(encoder.FileExtensions, nameof(encoder.FileExtensions));
+ Guard.NotNullOrEmpty(encoder.MimeTypes, nameof(encoder.MimeTypes));
lock (this.syncRoot)
{
- if (this.GuardDuplicate(format))
- {
- this.imageFormatsList.Add(format);
-
- this.SetMaxHeaderSize();
- }
+ this.encoders.Add(encoder);
}
}
///
- /// Checks to ensure duplicate image formats are not added.
+ /// Creates the default instance, with Png, Jpeg, Gif and Bmp preregisterd (if they have been referenced)
///
- /// 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));
- }
-
- // ReSharper disable once ConvertClosureToMethodGroup
- // Prevents method group allocation
- if (format.SupportedExtensions.Any(e => string.IsNullOrWhiteSpace(e)))
- {
- throw new ArgumentException("The supported extensions should not contain empty values.", nameof(format));
- }
-
- // 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;
- }
-
- if (imageFormat.SupportedExtensions.Intersect(format.SupportedExtensions, StringComparer.OrdinalIgnoreCase).Any())
- {
- return false;
- }
- }
+ Configuration config = new Configuration();
- return true;
+ // lets try auto loading the known image formats
+ config.AddImageFormat(new Formats.PngEncoder());
+ config.AddImageFormat(new Formats.JpegEncoder());
+ config.AddImageFormat(new Formats.GifEncoder());
+ config.AddImageFormat(new Formats.BmpEncoder());
+
+ config.AddImageFormat(new Formats.PngDecoder());
+ config.AddImageFormat(new Formats.JpegDecoder());
+ config.AddImageFormat(new Formats.GifDecoder());
+ config.AddImageFormat(new Formats.BmpDecoder());
+ return config;
}
///
@@ -200,7 +137,7 @@ namespace ImageSharp
///
private void SetMaxHeaderSize()
{
- this.MaxHeaderSize = this.imageFormatsList.Max(x => x.HeaderSize);
+ this.MaxHeaderSize = this.decoders.Max(x => x.HeaderSize);
}
}
}
diff --git a/src/ImageSharp/Formats/Bmp/BmpConstants.cs b/src/ImageSharp/Formats/Bmp/BmpConstants.cs
new file mode 100644
index 000000000..f2454f24d
--- /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 mimetypes 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..9ff331490 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;
@@ -28,7 +29,24 @@ namespace ImageSharp.Formats
public class BmpDecoder : IImageDecoder
{
///
- public Image Decode(Configuration configuration, Stream stream, IDecoderOptions options)
+ public IEnumerable MimeTypes => BmpConstants.MimeTypes;
+
+ ///
+ public IEnumerable FileExtensions => BmpConstants.FileExtensions;
+
+ ///
+ public int HeaderSize => 2;
+
+ ///
+ public bool IsSupportedFileFormat(Span header)
+ {
+ return header.Length >= this.HeaderSize &&
+ header[0] == 0x42 && // B
+ header[1] == 0x4D; // M
+ }
+
+ ///
+ public Image Decode(Configuration configuration, Stream stream)
where TPixel : struct, IPixel
{
diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoder.cs b/src/ImageSharp/Formats/Bmp/BmpEncoder.cs
index dc2bc0e97..25db0eda0 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;
@@ -16,26 +17,23 @@ namespace ImageSharp.Formats
/// The encoder can currently only write 24-bit rgb images to streams.
public class BmpEncoder : IImageEncoder
{
+ ///
+ /// Gets or sets the number of bits per pixel.
+ ///
+ public BmpBitsPerPixel BitsPerPixel { get; set; } = BmpBitsPerPixel.Pixel24;
+
///
- public void Encode(Image image, Stream stream, IEncoderOptions options)
- where TPixel : struct, IPixel
- {
- IBmpEncoderOptions bmpOptions = BmpEncoderOptions.Create(options);
+ public IEnumerable MimeTypes => BmpConstants.MimeTypes;
- this.Encode(image, stream, bmpOptions);
- }
+ ///
+ public IEnumerable FileExtensions => BmpConstants.FileExtensions;
- ///
- /// Encodes the image to the specified stream from the .
- ///
- /// 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 void Encode(Image image, Stream stream)
where TPixel : struct, IPixel
{
- BmpEncoderCore encoder = new BmpEncoderCore(options);
+ BmpEncoderCore encoder = new BmpEncoderCore();
+ encoder.BitsPerPixel = this.BitsPerPixel;
encoder.Encode(image, stream);
}
}
diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
index 617edde8e..615ff23ee 100644
--- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
@@ -17,11 +17,6 @@ namespace ImageSharp.Formats
///
internal sealed class BmpEncoderCore
{
- ///
- /// The options for the encoder.
- ///
- private readonly IBmpEncoderOptions options;
-
///
/// The amount to pad each row by.
///
@@ -30,12 +25,15 @@ namespace ImageSharp.Formats
///
/// Initializes a new instance of the class.
///
- /// The options for the encoder.
- public BmpEncoderCore(IBmpEncoderOptions options)
+ public BmpEncoderCore()
{
- this.options = options ?? new BmpEncoderOptions();
}
+ ///
+ /// Gets or sets the BitsPerPixel
+ ///
+ public BmpBitsPerPixel BitsPerPixel { get; internal set; } = BmpBitsPerPixel.Pixel24;
+
///
/// Encodes the image to the specified stream from the .
///
@@ -49,9 +47,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 +134,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/BmpFormat.cs b/src/ImageSharp/Formats/Bmp/BmpFormat.cs
deleted file mode 100644
index bf73d3162..000000000
--- a/src/ImageSharp/Formats/Bmp/BmpFormat.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// Copyright (c) James Jackson-South and contributors.
-// Licensed under the Apache License, Version 2.0.
-//
-
-namespace ImageSharp.Formats
-{
- using System.Collections.Generic;
-
- ///
- /// Encapsulates the means to encode and decode bitmap images.
- ///
- public class BmpFormat : IImageFormat
- {
- ///
- public string MimeType => "image/bmp";
-
- ///
- public string Extension => "bmp";
-
- ///
- public IEnumerable SupportedExtensions => new string[] { "bmp", "dip" };
-
- ///
- 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
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs b/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs
deleted file mode 100644
index 6cf37cbae..000000000
--- a/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs
+++ /dev/null
@@ -1,18 +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 interface IBmpEncoderOptions : IEncoderOptions
- {
- ///
- /// Gets the number of bits per pixel.
- ///
- BmpBitsPerPixel BitsPerPixel { get; }
- }
-}
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/GifConstants.cs b/src/ImageSharp/Formats/Gif/GifConstants.cs
index 4af291c2b..5c4d806d7 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 bmp
+ ///
+ public static readonly IEnumerable MimeTypes = new[] { "image/gif" };
+
+ ///
+ /// The list of mimetypes that equate to a bmp
+ ///
+ public static readonly IEnumerable FileExtensions = new[] { "gif" };
}
}
diff --git a/src/ImageSharp/Formats/Gif/GifDecoder.cs b/src/ImageSharp/Formats/Gif/GifDecoder.cs
index 88aaccf6a..506b37dc8 100644
--- a/src/ImageSharp/Formats/Gif/GifDecoder.cs
+++ b/src/ImageSharp/Formats/Gif/GifDecoder.cs
@@ -6,8 +6,9 @@
namespace ImageSharp.Formats
{
using System;
+ using System.Collections.Generic;
using System.IO;
-
+ using System.Text;
using ImageSharp.PixelFormats;
///
@@ -16,27 +17,43 @@ namespace ImageSharp.Formats
public class GifDecoder : IImageDecoder
{
///
- public Image Decode(Configuration configuration, Stream stream, IDecoderOptions options)
+ public IEnumerable MimeTypes => GifConstants.MimeTypes;
- where TPixel : struct, IPixel
- {
- IGifDecoderOptions gifOptions = GifDecoderOptions.Create(options);
+ ///
+ public IEnumerable FileExtensions => GifConstants.FileExtensions;
- 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 int HeaderSize => 6;
+
+ ///
+ public bool IsSupportedFileFormat(Span 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 Image Decode(Configuration configuration, Stream stream)
where TPixel : struct, IPixel
{
- return new GifDecoderCore(options, configuration).Decode(stream);
+ var decoder = new GifDecoderCore(this.TextEncoding, configuration);
+ decoder.IgnoreMetadata = this.IgnoreMetadata;
+ return decoder.Decode(stream);
}
}
}
diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
index 5b56c4c02..0bd64b057 100644
--- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
@@ -25,11 +25,6 @@ namespace ImageSharp.Formats
///
private readonly byte[] buffer = new byte[16];
- ///
- /// The decoder options.
- ///
- private readonly IGifDecoderOptions options;
-
///
/// The global configuration.
///
@@ -83,14 +78,24 @@ namespace ImageSharp.Formats
///
/// Initializes a new instance of the class.
///
- /// The decoder options.
+ /// The decoder encoding.
/// The configuration.
- public GifDecoderCore(IGifDecoderOptions options, Configuration configuration)
+ public GifDecoderCore(Encoding encoding, Configuration configuration)
{
- this.options = options ?? new GifDecoderOptions();
+ this.TextEncoding = encoding ?? GifConstants.DefaultEncoding;
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.
///
@@ -268,7 +273,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;
@@ -279,7 +284,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
@@ -363,8 +368,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..f7dba9266 100644
--- a/src/ImageSharp/Formats/Gif/GifEncoder.cs
+++ b/src/ImageSharp/Formats/Gif/GifEncoder.cs
@@ -6,9 +6,11 @@
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.
@@ -16,25 +18,46 @@ namespace ImageSharp.Formats
public class GifEncoder : IImageEncoder
{
///
- public void Encode(Image image, Stream stream, IEncoderOptions options)
- where TPixel : struct, IPixel
- {
- IGifEncoderOptions gifOptions = GifEncoderOptions.Create(options);
+ public IEnumerable MimeTypes => GifConstants.MimeTypes;
- this.Encode(image, stream, gifOptions);
- }
+ ///
+ public IEnumerable FileExtensions => GifConstants.FileExtensions;
///
- /// Encodes the image to the specified stream from the .
+ /// Gets or sets a value indicating whether the metadata should be ignored when the image is being encoded.
///
- /// 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 bool IgnoreMetadata { get; set; } = false;
+
+ ///
+ /// 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; }
+
+ ///
+ public void Encode(Image image, Stream stream)
where TPixel : struct, IPixel
{
- GifEncoderCore encoder = new GifEncoderCore(options);
+ GifEncoderCore encoder = new GifEncoderCore(this.TextEncoding);
+ encoder.Quantizer = this.Quantizer;
+ encoder.Threshold = this.Threshold;
+ encoder.Quality = this.Quality;
+ encoder.IgnoreMetadata = this.IgnoreMetadata;
encoder.Encode(image, stream);
}
}
diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
index 5ef7ca165..bc7014f19 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.
///
@@ -43,17 +38,37 @@ namespace ImageSharp.Formats
///
/// Initializes a new instance of the class.
///
- /// The options for the encoder.
- public GifEncoderCore(IGifEncoderOptions options)
+ /// The encoding for the encoder.
+ public GifEncoderCore(Encoding encoding)
{
- this.options = options ?? new GifEncoderOptions();
+ this.TextEncoding = encoding ?? GifConstants.DefaultEncoding;
}
+ ///
+ /// Gets the TextEncoding
+ ///
+ public Encoding TextEncoding { get; private set; }
+
///
/// Gets or sets the quantizer for reducing the color count.
///
public IQuantizer Quantizer { get; set; }
+ ///
+ /// Gets or sets the threshold.
+ ///
+ public byte Threshold { get; internal set; }
+
+ ///
+ /// Gets or sets the quality of output for images.
+ ///
+ public int Quality { get; internal set; }
+
+ ///
+ /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
+ ///
+ public bool IgnoreMetadata { get; internal set; }
+
///
/// Encodes the image to the specified stream from the .
///
@@ -66,13 +81,13 @@ 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;
+ int quality = this.Quality;
quality = quality > 0 ? quality.Clamp(1, 256) : 256;
// Get the number of bits.
@@ -240,7 +255,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 +266,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
deleted file mode 100644
index 2851b0b6b..000000000
--- a/src/ImageSharp/Formats/Gif/GifFormat.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
-{
- using System.Collections.Generic;
-
- ///
- /// Encapsulates the means to encode and decode gif images.
- ///
- public class GifFormat : IImageFormat
- {
- ///
- public string Extension => "gif";
-
- ///
- public string MimeType => "image/gif";
-
- ///
- public IEnumerable SupportedExtensions => new string[] { "gif" };
-
- ///
- 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
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Gif/IGifDecoderOptions.cs b/src/ImageSharp/Formats/Gif/IGifDecoderOptions.cs
deleted file mode 100644
index 729bf1d11..000000000
--- a/src/ImageSharp/Formats/Gif/IGifDecoderOptions.cs
+++ /dev/null
@@ -1,20 +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 interface IGifDecoderOptions : IDecoderOptions
- {
- ///
- /// Gets the encoding that should be used when reading comments.
- ///
- Encoding TextEncoding { get; }
- }
-}
diff --git a/src/ImageSharp/Formats/Gif/IGifEncoderOptions.cs b/src/ImageSharp/Formats/Gif/IGifEncoderOptions.cs
deleted file mode 100644
index c1d6b7ad8..000000000
--- a/src/ImageSharp/Formats/Gif/IGifEncoderOptions.cs
+++ /dev/null
@@ -1,38 +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 interface IGifEncoderOptions : IEncoderOptions
- {
- ///
- /// Gets the encoding that should be used when writing comments.
- ///
- Encoding TextEncoding { get; }
-
- ///
- /// Gets the quality of output for images.
- ///
- /// For gifs the value ranges from 1 to 256.
- int Quality { get; }
-
- ///
- /// Gets the transparency threshold.
- ///
- byte Threshold { get; }
-
- ///
- /// Gets the quantizer for reducing the color count.
- ///
- 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/IDecoderOptions.cs b/src/ImageSharp/Formats/IDecoderOptions.cs
deleted file mode 100644
index cdfd90d5e..000000000
--- a/src/ImageSharp/Formats/IDecoderOptions.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 decoder options.
- ///
- public interface IDecoderOptions
- {
- ///
- /// Gets a value indicating whether the metadata should be ignored when the image is being decoded.
- ///
- bool IgnoreMetadata { get; }
- }
-}
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..ff655d718 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;
@@ -15,15 +16,40 @@ namespace ImageSharp.Formats
///
public interface IImageDecoder
{
+ ///
+ /// Gets the collection of mime types that this decoder supports decoding on.
+ ///
+ IEnumerable MimeTypes { get; }
+
+ ///
+ /// Gets the collection of file extensionsthis decoder supports decoding.
+ ///
+ IEnumerable FileExtensions { 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(Span header);
+
///
/// Decodes the image from the specified stream to the .
///
/// 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..465f8eec5 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;
@@ -15,14 +16,23 @@ namespace ImageSharp.Formats
///
public interface IImageEncoder
{
+ ///
+ /// Gets the collection of mime types that this decoder supports encoding for.
+ ///
+ IEnumerable MimeTypes { get; }
+
+ ///
+ /// Gets the collection of file extensionsthis decoder supports encoding for.
+ ///
+ IEnumerable FileExtensions { get; }
+
///
/// Encodes the image to the specified stream from the .
///
/// 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
deleted file mode 100644
index de2e400fa..000000000
--- a/src/ImageSharp/Formats/IImageFormat.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-//
-// Copyright (c) James Jackson-South and contributors.
-// Licensed under the Apache License, Version 2.0.
-//
-
-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
- ///
- public interface IImageFormat
- {
- ///
- /// Gets the standard identifier used on the Internet to indicate the type of data that a file contains.
- ///
- string MimeType { get; }
-
- ///
- /// Gets the default file extension for this format.
- ///
- string Extension { get; }
-
- ///
- /// Gets the supported file extensions for this format.
- ///
- ///
- /// The supported file extension.
- ///
- IEnumerable SupportedExtensions { get; }
-
- ///
- /// Gets the image encoder for encoding an image from a stream.
- ///
- 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);
- }
-}
diff --git a/src/ImageSharp/Formats/Jpeg/IJpegEncoderOptions.cs b/src/ImageSharp/Formats/Jpeg/IJpegEncoderOptions.cs
deleted file mode 100644
index a54517965..000000000
--- a/src/ImageSharp/Formats/Jpeg/IJpegEncoderOptions.cs
+++ /dev/null
@@ -1,26 +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 interface IJpegEncoderOptions : IEncoderOptions
- {
- ///
- /// Gets 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.
- int Quality { get; }
-
- ///
- /// Gets the subsample ration, that will be used to encode the image.
- ///
- /// The subsample ratio of the jpg image.
- JpegSubsample? Subsample { get; }
- }
-}
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/JpegConstants.cs b/src/ImageSharp/Formats/Jpeg/JpegConstants.cs
index dcda39842..959813611 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 mimetypes 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 56d025504..09575a12e 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs
@@ -6,6 +6,7 @@
namespace ImageSharp.Formats
{
using System;
+ using System.Collections.Generic;
using System.IO;
using ImageSharp.PixelFormats;
@@ -15,16 +16,87 @@ namespace ImageSharp.Formats
///
public class JpegDecoder : IImageDecoder
{
+ ///
+ /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
+ ///
+ public bool IgnoreMetadata { get; set; }
+
+ ///
+ public IEnumerable MimeTypes => JpegConstants.MimeTypes;
+
+ ///
+ public IEnumerable FileExtensions => JpegConstants.FileExtensions;
+
+ ///
+ public int HeaderSize => 11;
+
+ ///
+ public bool IsSupportedFileFormat(Span header)
+ {
+ return header.Length >= this.HeaderSize &&
+ (IsJfif(header) || IsExif(header) || IsJpeg(header));
+ }
+
///
- 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 (JpegDecoderCore decoder = new JpegDecoderCore(options, configuration))
+ using (JpegDecoderCore decoder = new JpegDecoderCore(configuration))
{
+ decoder.IgnoreMetadata = this.IgnoreMetadata;
return decoder.Decode(stream);
}
}
+
+ ///
+ /// Returns a value indicating whether the given bytes identify Jfif data.
+ ///
+ /// The bytes representing the file header.
+ /// The
+ private static bool IsJfif(Span 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(Span 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(Span header)
+ {
+ bool isJpg =
+ header[0] == 0xFF && // 255
+ header[1] == 0xD8; // 216
+
+ return isJpg;
+ }
}
}
diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
index 971684371..f6456620e 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
@@ -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,10 @@ namespace ImageSharp.Formats
///
/// Initializes a new instance of the class.
///
- /// The decoder options.
/// The configuration.
- public JpegDecoderCore(IDecoderOptions options, Configuration configuration)
+ public JpegDecoderCore(Configuration configuration)
{
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 +183,11 @@ namespace ImageSharp.Formats
///
public int TotalMCUCount => this.MCUCountX * this.MCUCountY;
+ ///
+ /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
+ ///
+ public bool IgnoreMetadata { get; internal set; }
+
///
/// Decodes the image from the specified and sets
/// the data to image.
@@ -938,7 +936,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 +966,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..f76df0585 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;
@@ -14,14 +16,29 @@ namespace ImageSharp.Formats
///
public class JpegEncoder : IImageEncoder
{
+ ///
+ /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
+ ///
+ public bool IgnoreMetadata { get; set; }
+
+ ///
+ /// 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; }
+
///
- public void Encode(Image image, Stream stream, IEncoderOptions options)
- where TPixel : struct, IPixel
- {
- IJpegEncoderOptions gifOptions = JpegEncoderOptions.Create(options);
+ public IEnumerable MimeTypes => JpegConstants.MimeTypes;
- this.Encode(image, stream, gifOptions);
- }
+ ///
+ public IEnumerable FileExtensions => JpegConstants.FileExtensions;
///
/// Encodes the image to the specified stream from the .
@@ -29,12 +46,23 @@ 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);
+ JpegEncoderCore encoder = new JpegEncoderCore();
+
+ var quality = this.Quality;
+ if (quality == 0)
+ {
+ quality = 75;
+ }
+
+ encoder.Quality = quality;
+ encoder.Subsample = this.Subsample ?? (quality >= 91 ? JpegSubsample.Ratio444 : JpegSubsample.Ratio420);
+
+ encoder.IgnoreMetadata = this.IgnoreMetadata;
+
+ encoder.Encode(image, stream);
}
}
}
diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
index b65a56e73..168e47311 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
@@ -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.
///
@@ -154,20 +149,30 @@ namespace ImageSharp.Formats
///
private Stream outputStream;
- ///
- /// The subsampling method to use.
- ///
- private JpegSubsample subsample;
-
///
/// Initializes a new instance of the class.
///
- /// The options for the encoder.
- public JpegEncoderCore(IJpegEncoderOptions options)
+ public JpegEncoderCore()
{
- this.options = options ?? new JpegEncoderOptions();
}
+ ///
+ /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
+ ///
+ public bool IgnoreMetadata { get; internal set; } = 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).
+ ///
+ /// The quality of the jpg image from 0 to 100.
+ public int Quality { get; internal set; }
+
+ ///
+ /// Gets or sets the subsampling method to use.
+ ///
+ public JpegSubsample? Subsample { get; internal set; }
+
///
/// Encode writes the image to the jpeg baseline format with the given options.
///
@@ -186,21 +191,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 +785,7 @@ namespace ImageSharp.Formats
private void WriteProfiles(Image image)
where TPixel : struct, IPixel
{
- if (this.options.IgnoreMetadata)
+ if (this.IgnoreMetadata)
{
return;
}
@@ -810,7 +807,7 @@ namespace ImageSharp.Formats
byte[] subsamples = { 0x22, 0x11, 0x11 };
byte[] chroma = { 0x00, 0x01, 0x01 };
- switch (this.subsample)
+ switch (this.Subsample)
{
case JpegSubsample.Ratio444:
subsamples = new byte[] { 0x11, 0x11, 0x11 };
@@ -866,7 +863,7 @@ namespace ImageSharp.Formats
// TODO: We should allow grayscale writing.
this.outputStream.Write(SosHeaderYCbCr, 0, SosHeaderYCbCr.Length);
- switch (this.subsample)
+ switch (this.Subsample)
{
case JpegSubsample.Ratio444:
this.Encode444(pixels);
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
deleted file mode 100644
index b93c6ae69..000000000
--- a/src/ImageSharp/Formats/Jpeg/JpegFormat.cs
+++ /dev/null
@@ -1,89 +0,0 @@
-//
-// Copyright (c) James Jackson-South and contributors.
-// Licensed under the Apache License, Version 2.0.
-//
-
-namespace ImageSharp.Formats
-{
- using System.Collections.Generic;
-
- ///
- /// Encapsulates the means to encode and decode jpeg images.
- ///
- public class JpegFormat : IImageFormat
- {
- ///
- public string MimeType => "image/jpeg";
-
- ///
- public string Extension => "jpg";
-
- ///
- public IEnumerable SupportedExtensions => new string[] { "jpg", "jpeg", "jfif" };
-
- ///
- 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;
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Png/IPngDecoderOptions.cs b/src/ImageSharp/Formats/Png/IPngDecoderOptions.cs
deleted file mode 100644
index cc6d194bf..000000000
--- a/src/ImageSharp/Formats/Png/IPngDecoderOptions.cs
+++ /dev/null
@@ -1,20 +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 interface IPngDecoderOptions : IDecoderOptions
- {
- ///
- /// Gets the encoding that should be used when reading text chunks.
- ///
- Encoding TextEncoding { get; }
- }
-}
diff --git a/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs b/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs
deleted file mode 100644
index 0008080d3..000000000
--- a/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs
+++ /dev/null
@@ -1,54 +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 interface IPngEncoderOptions : IEncoderOptions
- {
- ///
- /// Gets the quality of output for images.
- ///
- int Quality { get; }
-
- ///
- /// Gets the png color type
- ///
- PngColorType PngColorType { get; }
-
- ///
- /// Gets the compression level 1-9.
- ///
- int CompressionLevel { get; }
-
- ///
- /// Gets the gamma value, that will be written
- /// the the stream, when the property
- /// is set to true.
- ///
- /// The gamma value of the image.
- float Gamma { get; }
-
- ///
- /// Gets quantizer for reducing the color count.
- ///
- IQuantizer Quantizer { get; }
-
- ///
- /// Gets the transparency threshold.
- ///
- byte Threshold { get; }
-
- ///
- /// Gets a value indicating whether this instance should write
- /// gamma information to the stream.
- ///
- bool WriteGamma { get; }
- }
-}
diff --git a/src/ImageSharp/Formats/Png/ImageExtensions.cs b/src/ImageSharp/Formats/Png/ImageExtensions.cs
index 44f242b3f..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
{
- PngEncoder 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/PngConstants.cs b/src/ImageSharp/Formats/Png/PngConstants.cs
new file mode 100644
index 000000000..b44ab7663
--- /dev/null
+++ b/src/ImageSharp/Formats/Png/PngConstants.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.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 jpeg
+ ///
+ public static readonly IEnumerable MimeTypes = new[] { "image/png" };
+
+ ///
+ /// The list of mimetypes that equate to a jpeg
+ ///
+ public static readonly IEnumerable FileExtensions = new[] { "png" };
+ }
+}
diff --git a/src/ImageSharp/Formats/Png/PngDecoder.cs b/src/ImageSharp/Formats/Png/PngDecoder.cs
index 3a34147e2..da00ff906 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;
///
@@ -32,14 +33,37 @@ namespace ImageSharp.Formats
///
public class PngDecoder : IImageDecoder
{
+ ///
+ /// 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 IEnumerable MimeTypes => PngConstants.MimeTypes;
- where TPixel : struct, IPixel
- {
- IPngDecoderOptions pngOptions = PngDecoderOptions.Create(options);
+ ///
+ public IEnumerable FileExtensions => PngConstants.FileExtensions;
- return this.Decode(configuration, stream, pngOptions);
+ ///
+ public int HeaderSize => 8;
+
+ ///
+ /// Gets or sets the encoding that should be used when reading text chunks.
+ ///
+ public Encoding TextEncoding { get; set; } = PngConstants.DefaultEncoding;
+
+ ///
+ public bool IsSupportedFileFormat(Span 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
}
///
@@ -48,12 +72,13 @@ 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.TextEncoding);
+ decoder.IgnoreMetadata = this.IgnoreMetadata;
+ return decoder.Decode(stream);
}
}
}
diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
index 2ff6a4308..b1b98eca5 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;
@@ -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,21 +149,31 @@ namespace ImageSharp.Formats
///
private int currentRowBytesRead;
+ ///
+ /// Gets or sets the png color type
+ ///
+ private PngColorType pngColorType;
+
///
/// Initializes a new instance of the class.
///
- /// The decoder options.
/// The configuration.
- public PngDecoderCore(IPngDecoderOptions options, Configuration configuration)
+ /// The text encoding.
+ public PngDecoderCore(Configuration configuration, Encoding encoding)
{
this.configuration = configuration ?? Configuration.Default;
- this.options = options ?? new PngDecoderOptions();
+ this.TextEncoding = encoding ?? PngConstants.DefaultEncoding;
}
///
- /// Gets or sets the png color type
+ /// Gets the encoding to use
+ ///
+ public Encoding TextEncoding { get; private set; }
+
+ ///
+ /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
///
- public PngColorType PngColorType { get; set; }
+ public bool IgnoreMetadata { get; internal set; }
///
/// Decodes the stream to the image.
@@ -221,7 +226,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 +348,7 @@ namespace ImageSharp.Formats
/// The
private int CalculateBytesPerPixel()
{
- switch (this.PngColorType)
+ switch (this.pngColorType)
{
case PngColorType.Grayscale:
return 1;
@@ -572,7 +576,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 +735,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 +900,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 +916,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 +971,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..023e465e9 100644
--- a/src/ImageSharp/Formats/Png/PngEncoder.cs
+++ b/src/ImageSharp/Formats/Png/PngEncoder.cs
@@ -5,9 +5,11 @@
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.
@@ -15,13 +17,55 @@ namespace ImageSharp.Formats
public class PngEncoder : IImageEncoder
{
///
- public void Encode(Image image, Stream stream, IEncoderOptions options)
- where TPixel : struct, IPixel
- {
- IPngEncoderOptions pngOptions = PngEncoderOptions.Create(options);
+ public IEnumerable MimeTypes => PngConstants.MimeTypes;
- this.Encode(image, stream, pngOptions);
- }
+ ///
+ public IEnumerable FileExtensions => PngConstants.FileExtensions;
+
+ ///
+ /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
+ ///
+ public bool IgnoreMetadata { get; set; }
+
+ ///
+ /// 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; }
///
/// Encodes the image to the specified stream from the .
@@ -29,12 +73,21 @@ 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 encode = new PngEncoderCore())
{
+ encode.IgnoreMetadata = this.IgnoreMetadata;
+
+ encode.Quality = this.Quality > 0 ? this.Quality.Clamp(1, int.MaxValue) : int.MaxValue;
+ encode.PngColorType = this.PngColorType;
+ encode.CompressionLevel = this.CompressionLevel;
+ encode.Gamma = this.Gamma;
+ encode.Quantizer = this.Quantizer;
+ encode.Threshold = this.Threshold;
+ encode.WriteGamma = this.WriteGamma;
+
encode.Encode(image, stream);
}
}
diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
index 645df0548..c96d60dbd 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.
///
@@ -131,12 +121,50 @@ namespace ImageSharp.Formats
///
/// Initializes a new instance of the class.
///
- /// The options for the encoder.
- public PngEncoderCore(IPngEncoderOptions options)
+ public PngEncoderCore()
{
- this.options = options ?? new PngEncoderOptions();
}
+ ///
+ /// Gets or sets a value indicating whether to ignore metadata
+ ///
+ public bool IgnoreMetadata { get; internal set; }
+
+ ///
+ /// Gets or sets the Quality value
+ ///
+ public int Quality { get; internal set; }
+
+ ///
+ /// Gets or sets the Quality value
+ ///
+ public PngColorType PngColorType { get; internal set; }
+
+ ///
+ /// Gets or sets the CompressionLevel value
+ ///
+ public int CompressionLevel { get; internal set; }
+
+ ///
+ /// Gets or sets the Gamma value
+ ///
+ public float Gamma { get; internal set; }
+
+ ///
+ /// Gets or sets the Quantizer value
+ ///
+ public IQuantizer Quantizer { get; internal set; }
+
+ ///
+ /// Gets or sets the Threshold value
+ ///
+ public byte Threshold { get; internal set; }
+
+ ///
+ /// Gets or sets a value indicating whether to Write Gamma
+ ///
+ public bool WriteGamma { get; internal set; }
+
///
/// Encodes the image to the specified stream from the .
///
@@ -164,27 +192,23 @@ 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;
+ this.pngColorType = this.PngColorType;
+ this.quantizer = this.Quantizer;
// Set correct color type if the color count is 256 or less.
- if (this.quality <= 256)
+ if (this.Quality <= 256)
{
this.pngColorType = PngColorType.Palette;
}
- if (this.pngColorType == PngColorType.Palette && this.quality > 256)
+ if (this.pngColorType == PngColorType.Palette && this.Quality > 256)
{
- this.quality = 256;
+ this.Quality = 256;
}
// Set correct bit depth.
- this.bitDepth = this.quality <= 256
- ? (byte)ImageMaths.GetBitsNeededForColorDepth(this.quality).Clamp(1, 8)
+ this.bitDepth = this.Quality <= 256
+ ? (byte)ImageMaths.GetBitsNeededForColorDepth(this.Quality).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 +538,7 @@ namespace ImageSharp.Formats
private QuantizedImage WritePaletteChunk(Stream stream, PngHeader header, ImageBase image)
where TPixel : struct, IPixel
{
- if (this.quality > 256)
+ if (this.Quality > 256)
{
return null;
}
@@ -525,7 +549,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.Quality);
// Grab the palette and write it to the stream.
TPixel[] palette = quantized.Palette;
@@ -552,7 +576,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 +634,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 +679,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
deleted file mode 100644
index 0f5a74da0..000000000
--- a/src/ImageSharp/Formats/Png/PngFormat.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.Collections.Generic;
-
- ///
- /// Encapsulates the means to encode and decode png images.
- ///
- public class PngFormat : IImageFormat
- {
- ///
- public string MimeType => "image/png";
-
- ///
- public string Extension => "png";
-
- ///
- public IEnumerable SupportedExtensions => new string[] { "png" };
-
- ///
- 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
- }
- }
-}
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..2730da8f2 100644
--- a/src/ImageSharp/Image/Image.Decode.cs
+++ b/src/ImageSharp/Image/Image.Decode.cs
@@ -23,7 +23,7 @@ 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)
+ private static IImageDecoder DiscoverDecoder(Stream stream, Configuration config)
{
// This is probably a candidate for making into a public API in the future!
int maxHeaderSize = config.MaxHeaderSize;
@@ -32,14 +32,14 @@ namespace ImageSharp
return null;
}
- IImageFormat format;
+ IImageDecoder format;
byte[] header = ArrayPool.Shared.Rent(maxHeaderSize);
try
{
long startPosition = stream.Position;
stream.Read(header, 0, maxHeaderSize);
stream.Position = startPosition;
- format = config.ImageFormats.FirstOrDefault(x => x.IsSupportedFileFormat(header));
+ format = config.ImageDecoders.LastOrDefault(x => x.IsSupportedFileFormat(header)); // we should use last in case user has registerd a new one with their own settings
}
finally
{
@@ -49,28 +49,28 @@ namespace ImageSharp
return format;
}
+#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, IImageDecoder decoder) 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);
+ 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, decoder);
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Image/Image.FromBytes.cs b/src/ImageSharp/Image/Image.FromBytes.cs
index c7309c4b1..8cc0e8f37 100644
--- a/src/ImageSharp/Image/Image.FromBytes.cs
+++ b/src/ImageSharp/Image/Image.FromBytes.cs
@@ -20,15 +20,15 @@ namespace ImageSharp
///
/// 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 string mimeType) => Load(null, data, out mimeType);
///
/// Create a new instance of the class from the given byte array.
@@ -36,33 +36,33 @@ namespace ImageSharp
/// 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.
+ /// 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 string mimeType) => Load(config, data, out mimeType);
///
- /// 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 +73,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 string mimeType)
where TPixel : struct, IPixel
{
- return Load(null, data, options);
+ return Load(null, data, out mimeType);
}
///
/// 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 (MemoryStream ms = new MemoryStream(data))
+ {
+ return Load(config, ms);
+ }
}
///
/// 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 string mimeType)
where TPixel : struct, IPixel
{
- return Load(data, decoder, null);
+ using (MemoryStream ms = new MemoryStream(data))
+ {
+ return Load(config, ms, out mimeType);
+ }
}
///
/// 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 (MemoryStream ms = new MemoryStream(data))
{
- return Load(config, ms, options);
+ return Load(ms, 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 (MemoryStream ms = new MemoryStream(data))
{
- return Load(ms, decoder, options);
+ return Load(config, ms, decoder);
}
}
}
diff --git a/src/ImageSharp/Image/Image.FromFile.cs b/src/ImageSharp/Image/Image.FromFile.cs
index a135c43f5..991294921 100644
--- a/src/ImageSharp/Image/Image.FromFile.cs
+++ b/src/ImageSharp/Image/Image.FromFile.cs
@@ -30,12 +30,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 string mimeType) => Load(path, out mimeType);
///
/// Create a new instance of the class from the given file.
@@ -51,37 +51,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 string mimeType) => Load(config, path, out mimeType);
///
/// 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 +95,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 string mimeType)
where TPixel : struct, IPixel
{
- return Load(null, path, options);
+ return Load(null, path, out mimeType);
}
///
/// 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 +127,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 s = config.FileSystem.OpenRead(path))
+ {
+ return Load(config, s);
+ }
}
///
/// 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 string mimeType)
where TPixel : struct, IPixel
{
- return Load(path, decoder, null);
+ config = config ?? Configuration.Default;
+ using (Stream s = config.FileSystem.OpenRead(path))
+ {
+ return Load(config, s, out mimeType);
+ }
}
///
/// 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;
+ config = config ?? Configuration.Default;
using (Stream s = config.FileSystem.OpenRead(path))
{
- return Load(s, decoder, options);
+ return Load(config, s, decoder);
}
}
}
diff --git a/src/ImageSharp/Image/Image.FromStream.cs b/src/ImageSharp/Image/Image.FromStream.cs
index 1bcb5adc9..79c66af90 100644
--- a/src/ImageSharp/Image/Image.FromStream.cs
+++ b/src/ImageSharp/Image/Image.FromStream.cs
@@ -7,6 +7,7 @@ namespace ImageSharp
{
using System;
using System.IO;
+ using System.Linq;
using System.Text;
using Formats;
@@ -21,22 +22,22 @@ namespace ImageSharp
/// 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 string mimeType) => Load(stream, out mimeType);
///
/// 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 +64,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 string mimeType) => Load(config, stream, out mimeType);
///
/// Create a new instance of the class from the given stream.
@@ -84,44 +85,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 string mimeType)
where TPixel : struct, IPixel
{
- return Load(null, stream, options);
+ return Load(null, stream, out mimeType);
}
///
/// 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 +131,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,27 +158,30 @@ 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 string mimeType)
+ where TPixel : struct, IPixel
{
config = config ?? Configuration.Default;
- Image img = WithSeekableStream(stream, s => Decode(s, options, config));
+ mimeType = null;
+ (Image img, IImageDecoder decoder) data = WithSeekableStream(stream, s => Decode(s, config));
+
+ mimeType = data.decoder?.MimeTypes.FirstOrDefault();
- if (img != null)
+ if (data.img != null)
{
- return img;
+ return data.img;
}
StringBuilder stringBuilder = new StringBuilder();
- stringBuilder.AppendLine("Image cannot be loaded. Available formats:");
+ stringBuilder.AppendLine("Image cannot be loaded. Available decoders:");
- foreach (IImageFormat format in config.ImageFormats)
+ foreach (IImageDecoder format in config.ImageDecoders)
{
stringBuilder.AppendLine("-" + format);
}
diff --git a/src/ImageSharp/Image/Image{TPixel}.cs b/src/ImageSharp/Image/Image{TPixel}.cs
index 059ccb9a0..27f3801c4 100644
--- a/src/ImageSharp/Image/Image{TPixel}.cs
+++ b/src/ImageSharp/Image/Image{TPixel}.cs
@@ -11,6 +11,7 @@ namespace ImageSharp
using System.IO;
using System.Linq;
using System.Numerics;
+ using System.Text;
using System.Threading.Tasks;
using Formats;
@@ -94,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();
}
///
@@ -138,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.
///
@@ -162,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 mime type to save the image to.
/// Thrown if the stream is null.
/// The
- public Image Save(Stream stream)
+ public Image Save(Stream stream, string mimeType)
{
- return this.Save(stream, (IEncoderOptions)null);
- }
+ Guard.NotNullOrEmpty(mimeType, nameof(mimeType));
+ IImageEncoder encoder = this.Configuration.ImageEncoders?.LastOrDefault(x => x?.MimeTypes?.Contains(mimeType, StringComparer.OrdinalIgnoreCase) == true);
- ///
- /// 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)
+ {
+ StringBuilder 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 (IImageEncoder format in this.Configuration.ImageEncoders)
+ {
+ stringBuilder.AppendLine("-" + format);
+ }
- ///
- /// 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);
}
///
@@ -216,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;
}
@@ -249,52 +204,24 @@ 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
- public Image Save(string filePath, IEncoderOptions options)
- {
string ext = Path.GetExtension(filePath).Trim('.');
- IImageFormat format = this.Configuration.ImageFormats.SingleOrDefault(f => f.SupportedExtensions.Contains(ext, StringComparer.OrdinalIgnoreCase));
- if (format == null)
+ IImageEncoder encoder = this.Configuration.ImageEncoders?.LastOrDefault(x => x?.FileExtensions?.Contains(ext, StringComparer.OrdinalIgnoreCase) == true);
+ if (encoder == null)
{
- throw new InvalidOperationException($"No image formats have been registered for the file extension '{ext}'.");
- }
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.AppendLine($"Can't find encoder for file extention '{ext}'. Available encoded:");
- return this.Save(filePath, format, options);
- }
+ foreach (IImageEncoder format in this.Configuration.ImageEncoders)
+ {
+ stringBuilder.AppendLine("-" + format);
+ }
- ///
- /// Saves the image to the given stream using the currently loaded image format.
- ///
- /// The file path to save the image to.
- /// The format to save the image as.
- /// Thrown if the format is null.
- /// The
- public Image Save(string filePath, IImageFormat format)
- {
- return this.Save(filePath, format, null);
- }
+ throw new NotSupportedException(stringBuilder.ToString());
+ }
- ///
- /// Saves the image to the given stream using the currently loaded image format.
- ///
- /// The file path to save the image to.
- /// The format to save the image as.
- /// The options for the encoder.
- /// Thrown if the format is null.
- /// The
- public Image Save(string filePath, IImageFormat format, IEncoderOptions options)
- {
- Guard.NotNull(format, nameof(format));
- return this.Save(filePath, format.Encoder, options);
+ return this.Save(filePath, encoder);
}
///
@@ -305,24 +232,11 @@ namespace ImageSharp
/// Thrown if the encoder is null.
/// The
public Image Save(string filePath, IImageEncoder encoder)
- {
- return this.Save(filePath, encoder, null);
- }
-
- ///
- /// Saves the image to the given stream using the currently loaded image format.
- ///
- /// The file path to save the image to.
- /// The encoder to save the image with.
- /// The options for the encoder.
- /// Thrown if the encoder is null.
- /// The
- public Image Save(string filePath, IImageEncoder encoder, IEncoderOptions options)
{
Guard.NotNull(encoder, nameof(encoder));
using (Stream fs = this.Configuration.FileSystem.Create(filePath))
{
- return this.Save(fs, encoder, options);
+ return this.Save(fs, encoder);
}
}
#endif
@@ -330,21 +244,22 @@ namespace ImageSharp
///
public override string ToString()
{
- return $"Image: {this.Width}x{this.Height}";
+ return $"Image<{typeof(TPixel).Name}>: {this.Width}x{this.Height}";
}
///
/// Returns a Base64 encoded string from the given image.
///
///
+ /// The mimeType.
/// The
- public string ToBase64String()
+ public string ToBase64String(string mimeType)
{
using (MemoryStream stream = new MemoryStream())
{
- this.Save(stream);
+ this.Save(stream, mimeType);
stream.Flush();
- return $"data:{this.CurrentImageFormat.MimeType};base64,{Convert.ToBase64String(stream.ToArray())}";
+ return $"data:{mimeType};base64,{Convert.ToBase64String(stream.ToArray())}";
}
}
@@ -417,7 +332,6 @@ namespace ImageSharp
///
private void CopyProperties(IImage other)
{
- this.CurrentImageFormat = other.CurrentImageFormat;
this.MetaData = new ImageMetaData(other.MetaData);
}
}
diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj
index 17f7bf58f..6cc981f96 100644
--- a/src/ImageSharp/ImageSharp.csproj
+++ b/src/ImageSharp/ImageSharp.csproj
@@ -43,6 +43,7 @@
+
..\..\ImageSharp.ruleset
diff --git a/src/ImageSharp/MetaData/ImageMetaData.cs b/src/ImageSharp/MetaData/ImageMetaData.cs
index 91ea9ac4b..5361b486d 100644
--- a/src/ImageSharp/MetaData/ImageMetaData.cs
+++ b/src/ImageSharp/MetaData/ImageMetaData.cs
@@ -50,7 +50,6 @@ namespace ImageSharp
this.HorizontalResolution = other.HorizontalResolution;
this.VerticalResolution = other.VerticalResolution;
- this.Quality = other.Quality;
this.FrameDelay = other.FrameDelay;
this.DisposalMethod = other.DisposalMethod;
this.RepeatCount = other.RepeatCount;
@@ -127,11 +126,6 @@ namespace ImageSharp
/// A list of image properties.
public IList Properties { get; } = new List();
- ///
- /// Gets or sets the quality of the image. This affects the output quality of lossy image formats.
- ///
- public int Quality { get; set; }
-
///
/// Gets or sets the number of times any animation is repeated.
/// 0 means to repeat indefinitely.
diff --git a/tests/ImageSharp.Benchmarks/BenchmarkBase.cs b/tests/ImageSharp.Benchmarks/BenchmarkBase.cs
index d6e8ac692..41574d109 100644
--- a/tests/ImageSharp.Benchmarks/BenchmarkBase.cs
+++ b/tests/ImageSharp.Benchmarks/BenchmarkBase.cs
@@ -13,10 +13,6 @@
protected BenchmarkBase()
{
// Add Image Formats
- Configuration.Default.AddImageFormat(new JpegFormat());
- Configuration.Default.AddImageFormat(new PngFormat());
- Configuration.Default.AddImageFormat(new BmpFormat());
- Configuration.Default.AddImageFormat(new GifFormat());
}
}
}
diff --git a/tests/ImageSharp.Benchmarks/Image/EncodeIndexedPng.cs b/tests/ImageSharp.Benchmarks/Image/EncodeIndexedPng.cs
index 88e82f079..aa3112f52 100644
--- a/tests/ImageSharp.Benchmarks/Image/EncodeIndexedPng.cs
+++ b/tests/ImageSharp.Benchmarks/Image/EncodeIndexedPng.cs
@@ -53,9 +53,9 @@ namespace ImageSharp.Benchmarks.Image
{
using (MemoryStream memoryStream = new MemoryStream())
{
- PngEncoderOptions options = new PngEncoderOptions() { Quantizer = new OctreeQuantizer(), Quality = 256 };
+ PngEncoder encoder = new PngEncoder() { Quantizer = new OctreeQuantizer(), Quality = 256 };
- this.bmpCore.SaveAsPng(memoryStream, options);
+ this.bmpCore.SaveAsPng(memoryStream, encoder);
}
}
@@ -64,7 +64,7 @@ namespace ImageSharp.Benchmarks.Image
{
using (MemoryStream memoryStream = new MemoryStream())
{
- PngEncoderOptions options = new PngEncoderOptions { Quantizer = new OctreeQuantizer { Dither = false }, Quality = 256 };
+ PngEncoder options = new PngEncoder { Quantizer = new OctreeQuantizer { Dither = false }, Quality = 256 };
this.bmpCore.SaveAsPng(memoryStream, options);
}
@@ -75,7 +75,7 @@ namespace ImageSharp.Benchmarks.Image
{
using (MemoryStream memoryStream = new MemoryStream())
{
- PngEncoderOptions options = new PngEncoderOptions { Quantizer = new PaletteQuantizer(), Quality = 256 };
+ PngEncoder options = new PngEncoder { Quantizer = new PaletteQuantizer(), Quality = 256 };
this.bmpCore.SaveAsPng(memoryStream, options);
}
@@ -86,7 +86,7 @@ namespace ImageSharp.Benchmarks.Image
{
using (MemoryStream memoryStream = new MemoryStream())
{
- PngEncoderOptions options = new PngEncoderOptions { Quantizer = new PaletteQuantizer { Dither = false }, Quality = 256 };
+ PngEncoder options = new PngEncoder { Quantizer = new PaletteQuantizer { Dither = false }, Quality = 256 };
this.bmpCore.SaveAsPng(memoryStream, options);
}
@@ -97,7 +97,7 @@ namespace ImageSharp.Benchmarks.Image
{
using (MemoryStream memoryStream = new MemoryStream())
{
- PngEncoderOptions options = new PngEncoderOptions() { Quantizer = new WuQuantizer(), Quality = 256 };
+ PngEncoder options = new PngEncoder() { Quantizer = new WuQuantizer(), Quality = 256 };
this.bmpCore.SaveAsPng(memoryStream, options);
}
diff --git a/tests/ImageSharp.Benchmarks/Image/EncodePng.cs b/tests/ImageSharp.Benchmarks/Image/EncodePng.cs
index 3ec83aa7c..81bb235ee 100644
--- a/tests/ImageSharp.Benchmarks/Image/EncodePng.cs
+++ b/tests/ImageSharp.Benchmarks/Image/EncodePng.cs
@@ -71,7 +71,7 @@ namespace ImageSharp.Benchmarks.Image
new OctreeQuantizer()
: new PaletteQuantizer();
- PngEncoderOptions options = new PngEncoderOptions() { Quantizer = quantizer };
+ PngEncoder options = new PngEncoder() { Quantizer = quantizer };
this.bmpCore.SaveAsPng(memoryStream, options);
}
}
diff --git a/tests/ImageSharp.Tests/ConfigurationTests.cs b/tests/ImageSharp.Tests/ConfigurationTests.cs
index aa3c4edfc..e2d50649a 100644
--- a/tests/ImageSharp.Tests/ConfigurationTests.cs
+++ b/tests/ImageSharp.Tests/ConfigurationTests.cs
@@ -36,7 +36,8 @@ namespace ImageSharp.Tests
{
var configuration = Configuration.CreateDefaultInstance();
- Assert.Equal(4, configuration.ImageFormats.Count);
+ Assert.Equal(4, configuration.ImageDecoders.Count);
+ Assert.Equal(4, configuration.ImageDecoders.Count);
}
///
@@ -73,7 +74,8 @@ namespace ImageSharp.Tests
[Fact]
public void TestDefultConfigurationImageFormatsIsNotNull()
{
- Assert.True(Configuration.Default.ImageFormats != null);
+ Assert.True(Configuration.Default.ImageDecoders != null);
+ Assert.True(Configuration.Default.ImageEncoders != null);
}
///
@@ -85,163 +87,25 @@ namespace ImageSharp.Tests
{
Assert.Throws(() =>
{
- Configuration.Default.AddImageFormat(null);
+ Configuration.Default.AddImageFormat((IImageEncoder)null);
});
- }
-
- ///
- /// Tests the method throws an exception
- /// when the encoder is null.
- ///
- [Fact]
- public void TestAddImageFormatThrowsWithNullEncoder()
- {
- var format = new TestFormat { Encoder = null };
-
- Assert.Throws(() =>
- {
- Configuration.Default.AddImageFormat(format);
- });
- }
-
- ///
- /// Tests the method throws an exception
- /// when the decoder is null.
- ///
- [Fact]
- public void TestAddImageFormatThrowsWithNullDecoder()
- {
- var format = new TestFormat { Decoder = null };
-
- Assert.Throws(() =>
- {
- Configuration.Default.AddImageFormat(format);
- });
- }
-
- ///
- /// Tests the method throws an exception
- /// when the mime type is null or an empty string.
- ///
- [Fact]
- public void TestAddImageFormatThrowsWithNullOrEmptyMimeType()
- {
- var format = new TestFormat { MimeType = null };
-
Assert.Throws(() =>
{
- Configuration.Default.AddImageFormat(format);
- });
-
- format = new TestFormat { MimeType = string.Empty };
-
- Assert.Throws(() =>
- {
- Configuration.Default.AddImageFormat(format);
+ Configuration.Default.AddImageFormat((IImageDecoder)null);
});
}
- ///
- /// Tests the method throws an exception
- /// when the extension is null or an empty string.
- ///
- [Fact]
- public void TestAddImageFormatThrowsWithNullOrEmptyExtension()
- {
- var format = new TestFormat { Extension = null };
-
- Assert.Throws(() =>
- {
- Configuration.Default.AddImageFormat(format);
- });
-
- format = new TestFormat { Extension = string.Empty };
-
- Assert.Throws(() =>
- {
- Configuration.Default.AddImageFormat(format);
- });
- }
-
- ///
- /// Tests the method throws an exception
- /// when the supported extensions list is null or empty.
- ///
- [Fact]
- public void TestAddImageFormatThrowsWenSupportedExtensionsIsNullOrEmpty()
- {
- var format = new TestFormat { SupportedExtensions = null };
-
- Assert.Throws(() =>
- {
- Configuration.Default.AddImageFormat(format);
- });
-
- format = new TestFormat { SupportedExtensions = Enumerable.Empty() };
-
- Assert.Throws(() =>
- {
- Configuration.Default.AddImageFormat(format);
- });
- }
-
- ///
- /// Tests the method throws an exception
- /// when the supported extensions list does not contain the default extension.
- ///
- [Fact]
- public void TestAddImageFormatThrowsWithoutDefaultExtension()
- {
- var format = new TestFormat { Extension = "test" };
-
- Assert.Throws(() =>
- {
- Configuration.Default.AddImageFormat(format);
- });
- }
-
- ///
- /// Tests the method throws an exception
- /// when the supported extensions list contains an empty string.
- ///
- [Fact]
- public void TestAddImageFormatThrowsWithEmptySupportedExtension()
- {
- var format = new TestFormat
- {
- Extension = "test",
- SupportedExtensions = new[] { "test", string.Empty }
- };
-
- Assert.Throws(() =>
- {
- Configuration.Default.AddImageFormat(format);
- });
- }
-
- ///
- /// Test that the method ignores adding duplicate image formats.
- ///
- [Fact]
- public void TestConfigurationIgnoresDuplicateImageFormats()
- {
- Configuration.Default.AddImageFormat(new PngFormat());
- Configuration.Default.AddImageFormat(new PngFormat());
-
- Assert.True(Configuration.Default.ImageFormats.Count(i => i.GetType() == typeof(PngFormat)) == 1);
- }
-
///
/// Test that the default image constructors use default configuration.
///
[Fact]
public void TestImageUsesDefaultConfiguration()
{
- Configuration.Default.AddImageFormat(new PngFormat());
+ Configuration.Default.AddImageFormat(new PngDecoder());
var image = new Image(1, 1);
Assert.Equal(image.Configuration.ParallelOptions, Configuration.Default.ParallelOptions);
- Assert.Equal(image.Configuration.ImageFormats, Configuration.Default.ImageFormats);
+ Assert.Equal(image.Configuration.ImageDecoders, Configuration.Default.ImageDecoders);
}
///
@@ -250,60 +114,12 @@ namespace ImageSharp.Tests
[Fact]
public void TestImageCopiesConfiguration()
{
- Configuration.Default.AddImageFormat(new PngFormat());
+ Configuration.Default.AddImageFormat(new PngDecoder());
var image = new Image(1, 1);
var image2 = new Image(image);
Assert.Equal(image2.Configuration.ParallelOptions, image.Configuration.ParallelOptions);
- Assert.True(image2.Configuration.ImageFormats.SequenceEqual(image.Configuration.ImageFormats));
- }
-
- ///
- /// A test image format for testing the configuration.
- ///
- private class TestFormat : IImageFormat
- {
- ///
- /// Initializes a new instance of the class.
- ///
- public TestFormat()
- {
- this.Decoder = new JpegDecoder();
- this.Encoder = new JpegEncoder();
- this.Extension = "jpg";
- this.MimeType = "image/test";
- this.SupportedExtensions = new[] { "jpg" };
- }
-
- ///
- public IImageDecoder Decoder { get; set; }
-
- ///
- public IImageEncoder Encoder { get; set; }
-
- ///
- public string MimeType { get; set; }
-
- ///
- public string Extension { get; set; }
-
- ///
- public IEnumerable SupportedExtensions { get; set; }
-
- ///
- public int HeaderSize
- {
- get
- {
- throw new NotImplementedException();
- }
- }
-
- ///
- public bool IsSupportedFileFormat(byte[] header)
- {
- throw new NotImplementedException();
- }
+ Assert.True(image2.Configuration.ImageDecoders.SequenceEqual(image.Configuration.ImageDecoders));
}
}
}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Drawing/BeziersTests.cs b/tests/ImageSharp.Tests/Drawing/BeziersTests.cs
index 3d49a70b8..4b53bbb04 100644
--- a/tests/ImageSharp.Tests/Drawing/BeziersTests.cs
+++ b/tests/ImageSharp.Tests/Drawing/BeziersTests.cs
@@ -24,18 +24,15 @@ namespace ImageSharp.Tests.Drawing
string path = this.CreateOutputDirectory("Drawing", "BezierLine");
using (Image image = new Image(500, 500))
{
- using (FileStream output = File.OpenWrite($"{path}/Simple.png"))
- {
- image.BackgroundColor(Rgba32.Blue)
- .DrawBeziers(Rgba32.HotPink, 5,
- new[] {
+ image.BackgroundColor(Rgba32.Blue)
+ .DrawBeziers(Rgba32.HotPink, 5,
+ new[] {
new Vector2(10, 400),
new Vector2(30, 10),
new Vector2(240, 30),
new Vector2(300, 400)
- })
- .Save(output);
- }
+ })
+ .Save($"{path}/Simple.png");
using (PixelAccessor sourcePixels = image.Lock())
{
@@ -66,19 +63,16 @@ namespace ImageSharp.Tests.Drawing
using (Image image = new Image(500, 500))
{
- using (FileStream output = File.OpenWrite($"{path}/Opacity.png"))
- {
- image.BackgroundColor(Rgba32.Blue)
- .DrawBeziers(color,
- 10,
- new[] {
+ image.BackgroundColor(Rgba32.Blue)
+ .DrawBeziers(color,
+ 10,
+ new[] {
new Vector2(10, 400),
new Vector2(30, 10),
new Vector2(240, 30),
new Vector2(300, 400)
- })
- .Save(output);
- }
+ })
+ .Save($"{path}/Opacity.png");
//shift background color towards forground color by the opacity amount
Rgba32 mergedColor = new Rgba32(Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f / 255f));
diff --git a/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs b/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs
index 4ba4a3a83..50466fcdd 100644
--- a/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs
+++ b/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs
@@ -34,13 +34,10 @@ namespace ImageSharp.Tests.Drawing
ShapePath p = new ShapePath(linerSegemnt, bazierSegment);
- using (FileStream output = File.OpenWrite($"{path}/Simple.png"))
- {
- image
- .BackgroundColor(Rgba32.Blue)
- .Draw(Rgba32.HotPink, 5, p)
- .Save(output);
- }
+ image
+ .BackgroundColor(Rgba32.Blue)
+ .Draw(Rgba32.HotPink, 5, p)
+ .Save($"{path}/Simple.png");
using (PixelAccessor sourcePixels = image.Lock())
{
@@ -77,13 +74,10 @@ namespace ImageSharp.Tests.Drawing
using (Image image = new Image(500, 500))
{
- using (FileStream output = File.OpenWrite($"{path}/Opacity.png"))
- {
- image
- .BackgroundColor(Rgba32.Blue)
- .Draw(color, 10, p)
- .Save(output);
- }
+ image
+ .BackgroundColor(Rgba32.Blue)
+ .Draw(color, 10, p)
+ .Save($"{path}/Opacity.png");
//shift background color towards forground color by the opacity amount
Rgba32 mergedColor = new Rgba32(Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f / 255f));
@@ -115,11 +109,8 @@ namespace ImageSharp.Tests.Drawing
image.DrawLines(pen, new Vector2[] { new Vector2(100, 2), new Vector2(-10, i) });
}
- using (FileStream output = File.OpenWrite($"{path}/ClippedLines.png"))
- {
- image
- .Save(output);
- }
+ image
+ .Save($"{path}/ClippedLines.png");
using (PixelAccessor sourcePixels = image.Lock())
{
Assert.Equal(Rgba32.White, sourcePixels[0, 90]);
diff --git a/tests/ImageSharp.Tests/Drawing/FillPatternTests.cs b/tests/ImageSharp.Tests/Drawing/FillPatternTests.cs
index 7bacebe42..bbabdf0ea 100644
--- a/tests/ImageSharp.Tests/Drawing/FillPatternTests.cs
+++ b/tests/ImageSharp.Tests/Drawing/FillPatternTests.cs
@@ -25,10 +25,7 @@ namespace ImageSharp.Tests.Drawing
.Fill(background)
.Fill(brush);
- using (FileStream output = File.OpenWrite($"{path}/{name}.png"))
- {
- image.Save(output);
- }
+ image.Save($"{path}/{name}.png");
using (PixelAccessor sourcePixels = image.Lock())
{
@@ -54,10 +51,7 @@ namespace ImageSharp.Tests.Drawing
}
}
}
- using (FileStream output = File.OpenWrite($"{path}/{name}x4.png"))
- {
- image.Resize(80, 80).Save(output);
- }
+ image.Resize(80, 80).Save($"{path}/{name}x4.png");
}
}
diff --git a/tests/ImageSharp.Tests/Drawing/FillSolidBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillSolidBrushTests.cs
index dc0b83615..ce127cfe0 100644
--- a/tests/ImageSharp.Tests/Drawing/FillSolidBrushTests.cs
+++ b/tests/ImageSharp.Tests/Drawing/FillSolidBrushTests.cs
@@ -16,7 +16,7 @@ namespace ImageSharp.Tests.Drawing
using Xunit;
- public class FillSolidBrushTests: FileTestBase
+ public class FillSolidBrushTests : FileTestBase
{
[Fact]
public void ImageShouldBeFloodFilledWithColorOnDefaultBackground()
@@ -24,12 +24,9 @@ namespace ImageSharp.Tests.Drawing
string path = this.CreateOutputDirectory("Fill", "SolidBrush");
using (Image image = new Image(500, 500))
{
- using (FileStream output = File.OpenWrite($"{path}/DefaultBack.png"))
- {
- image
- .Fill(Rgba32.HotPink)
- .Save(output);
- }
+ image
+ .Fill(Rgba32.HotPink)
+ .Save($"{path}/DefaultBack.png");
using (PixelAccessor sourcePixels = image.Lock())
{
@@ -46,13 +43,10 @@ namespace ImageSharp.Tests.Drawing
string path = this.CreateOutputDirectory("Fill", "SolidBrush");
using (Image image = new Image(500, 500))
{
- using (FileStream output = File.OpenWrite($"{path}/Simple.png"))
- {
- image
- .BackgroundColor(Rgba32.Blue)
- .Fill(Rgba32.HotPink)
- .Save(output);
- }
+ image
+ .BackgroundColor(Rgba32.Blue)
+ .Fill(Rgba32.HotPink)
+ .Save($"{path}/Simple.png");
using (PixelAccessor sourcePixels = image.Lock())
{
@@ -71,13 +65,11 @@ namespace ImageSharp.Tests.Drawing
{
Rgba32 color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150);
- using (FileStream output = File.OpenWrite($"{path}/Opacity.png"))
- {
- image
- .BackgroundColor(Rgba32.Blue)
- .Fill(color)
- .Save(output);
- }
+ image
+ .BackgroundColor(Rgba32.Blue)
+ .Fill(color)
+ .Save($"{path}/Opacity.png");
+
//shift background color towards forground color by the opacity amount
Rgba32 mergedColor = new Rgba32(Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f / 255f));
diff --git a/tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs
index 1f35a3788..e058572fb 100644
--- a/tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs
+++ b/tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs
@@ -34,13 +34,10 @@ namespace ImageSharp.Tests.Drawing
using (Image image = new Image(500, 500))
{
- using (FileStream output = File.OpenWrite($"{path}/Simple.png"))
- {
- image
- .BackgroundColor(Rgba32.Blue)
- .Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1))
- .Save(output);
- }
+ image
+ .BackgroundColor(Rgba32.Blue)
+ .Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1))
+ .Save($"{path}/Simple.png");
using (PixelAccessor sourcePixels = image.Lock())
{
@@ -84,13 +81,10 @@ namespace ImageSharp.Tests.Drawing
using (Image image = new Image(500, 500))
{
- using (FileStream output = File.OpenWrite($"{path}/SimpleVanishHole.png"))
- {
- image
- .BackgroundColor(Rgba32.Blue)
- .Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1))
- .Save(output);
- }
+ image
+ .BackgroundColor(Rgba32.Blue)
+ .Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1))
+ .Save($"{path}/SimpleVanishHole.png");
using (PixelAccessor sourcePixels = image.Lock())
{
@@ -135,13 +129,10 @@ namespace ImageSharp.Tests.Drawing
using (Image image = new Image(500, 500))
{
- using (FileStream output = File.OpenWrite($"{path}/SimpleOverlapping.png"))
- {
- image
- .BackgroundColor(Rgba32.Blue)
- .Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1))
- .Save(output);
- }
+ image
+ .BackgroundColor(Rgba32.Blue)
+ .Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1))
+ .Save($"{path}/SimpleOverlapping.png");
using (PixelAccessor sourcePixels = image.Lock())
{
@@ -181,13 +172,10 @@ namespace ImageSharp.Tests.Drawing
using (Image image = new Image(500, 500))
{
- using (FileStream output = File.OpenWrite($"{path}/Dashed.png"))
- {
- image
- .BackgroundColor(Rgba32.Blue)
- .Draw(Pens.Dash(Rgba32.HotPink, 5), simplePath.Clip(hole1))
- .Save(output);
- }
+ image
+ .BackgroundColor(Rgba32.Blue)
+ .Draw(Pens.Dash(Rgba32.HotPink, 5), simplePath.Clip(hole1))
+ .Save($"{path}/Dashed.png");
}
}
@@ -209,13 +197,10 @@ namespace ImageSharp.Tests.Drawing
using (Image image = new Image(500, 500))
{
- using (FileStream output = File.OpenWrite($"{path}/Opacity.png"))
- {
- image
- .BackgroundColor(Rgba32.Blue)
- .Draw(color, 5, simplePath.Clip(hole1))
- .Save(output);
- }
+ image
+ .BackgroundColor(Rgba32.Blue)
+ .Draw(color, 5, simplePath.Clip(hole1))
+ .Save($"{path}/Opacity.png");
//shift background color towards forground color by the opacity amount
Rgba32 mergedColor = new Rgba32(Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f / 255f));
diff --git a/tests/ImageSharp.Tests/Drawing/LineTests.cs b/tests/ImageSharp.Tests/Drawing/LineTests.cs
index e751557b6..6c1e70013 100644
--- a/tests/ImageSharp.Tests/Drawing/LineTests.cs
+++ b/tests/ImageSharp.Tests/Drawing/LineTests.cs
@@ -23,18 +23,15 @@ namespace ImageSharp.Tests.Drawing
string path = this.CreateOutputDirectory("Drawing", "Lines");
using (Image image = new Image(500, 500))
{
- using (FileStream output = File.OpenWrite($"{path}/Simple.png"))
- {
- image
- .BackgroundColor(Rgba32.Blue)
- .DrawLines(Rgba32.HotPink, 5,
- new[] {
+ image
+ .BackgroundColor(Rgba32.Blue)
+ .DrawLines(Rgba32.HotPink, 5,
+ new[] {
new Vector2(10, 10),
new Vector2(200, 150),
new Vector2(50, 300)
- })
- .Save(output);
- }
+ })
+ .Save($"{path}/Simple.png");
using (PixelAccessor sourcePixels = image.Lock())
{
@@ -53,19 +50,16 @@ namespace ImageSharp.Tests.Drawing
string path = this.CreateOutputDirectory("Drawing", "Lines");
using (Image image = new Image(500, 500))
{
- using (FileStream output = File.OpenWrite($"{path}/Simple_noantialias.png"))
- {
- image
- .BackgroundColor(Rgba32.Blue)
- .DrawLines(Rgba32.HotPink, 5,
- new[] {
+ image
+ .BackgroundColor(Rgba32.Blue)
+ .DrawLines(Rgba32.HotPink, 5,
+ new[] {
new Vector2(10, 10),
new Vector2(200, 150),
new Vector2(50, 300)
- },
- new GraphicsOptions(false))
- .Save(output);
- }
+ },
+ new GraphicsOptions(false))
+ .Save($"{path}/Simple_noantialias.png");
using (PixelAccessor sourcePixels = image.Lock())
{
@@ -84,18 +78,15 @@ namespace ImageSharp.Tests.Drawing
string path = this.CreateOutputDirectory("Drawing", "Lines");
using (Image image = new Image(500, 500))
{
- using (FileStream output = File.OpenWrite($"{path}/Dashed.png"))
- {
- image
- .BackgroundColor(Rgba32.Blue)
- .DrawLines(Pens.Dash(Rgba32.HotPink, 5),
- new[] {
+ image
+ .BackgroundColor(Rgba32.Blue)
+ .DrawLines(Pens.Dash(Rgba32.HotPink, 5),
+ new[] {
new Vector2(10, 10),
new Vector2(200, 150),
new Vector2(50, 300)
- })
- .Save(output);
- }
+ })
+ .Save($"{path}/Dashed.png");
}
}
@@ -105,18 +96,15 @@ namespace ImageSharp.Tests.Drawing
string path = this.CreateOutputDirectory("Drawing", "Lines");
using (Image image = new Image(500, 500))
{
- using (FileStream output = File.OpenWrite($"{path}/Dot.png"))
- {
- image
- .BackgroundColor(Rgba32.Blue)
- .DrawLines(Pens.Dot(Rgba32.HotPink, 5),
- new[] {
+ image
+ .BackgroundColor(Rgba32.Blue)
+ .DrawLines(Pens.Dot(Rgba32.HotPink, 5),
+ new[] {
new Vector2(10, 10),
new Vector2(200, 150),
new Vector2(50, 300)
- })
- .Save(output);
- }
+ })
+ .Save($"{path}/Dot.png");
}
}
@@ -126,18 +114,15 @@ namespace ImageSharp.Tests.Drawing
string path = this.CreateOutputDirectory("Drawing", "Lines");
using (Image image = new Image(500, 500))
{
- using (FileStream output = File.OpenWrite($"{path}/DashDot.png"))
- {
- image
- .BackgroundColor(Rgba32.Blue)
- .DrawLines(Pens.DashDot(Rgba32.HotPink, 5),
- new[] {
+ image
+ .BackgroundColor(Rgba32.Blue)
+ .DrawLines(Pens.DashDot(Rgba32.HotPink, 5),
+ new[] {
new Vector2(10, 10),
new Vector2(200, 150),
new Vector2(50, 300)
- })
- .Save(output);
- }
+ })
+ .Save($"{path}/DashDot.png");
}
}
@@ -147,17 +132,14 @@ namespace ImageSharp.Tests.Drawing
string path = this.CreateOutputDirectory("Drawing", "Lines");
Image image = new Image(500, 500);
- using (FileStream output = File.OpenWrite($"{path}/DashDotDot.png"))
- {
- image
- .BackgroundColor(Rgba32.Blue)
- .DrawLines(Pens.DashDotDot(Rgba32.HotPink, 5), new[] {
+ image
+ .BackgroundColor(Rgba32.Blue)
+ .DrawLines(Pens.DashDotDot(Rgba32.HotPink, 5), new[] {
new Vector2(10, 10),
new Vector2(200, 150),
new Vector2(50, 300)
- })
- .Save(output);
- }
+ })
+ .Save($"{path}/DashDotDot.png");
}
[Fact]
@@ -169,21 +151,17 @@ namespace ImageSharp.Tests.Drawing
Image image = new Image(500, 500);
-
- using (FileStream output = File.OpenWrite($"{path}/Opacity.png"))
- {
- image
- .BackgroundColor(Rgba32.Blue)
- .DrawLines(color, 10, new[] {
+ image
+ .BackgroundColor(Rgba32.Blue)
+ .DrawLines(color, 10, new[] {
new Vector2(10, 10),
new Vector2(200, 150),
new Vector2(50, 300)
- })
- .Save(output);
- }
+ })
+ .Save($"{path}/Opacity.png");
//shift background color towards forground color by the opacity amount
- Rgba32 mergedColor = new Rgba32(Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f/255f));
+ Rgba32 mergedColor = new Rgba32(Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f / 255f));
using (PixelAccessor sourcePixels = image.Lock())
{
@@ -202,18 +180,15 @@ namespace ImageSharp.Tests.Drawing
Image image = new Image(500, 500);
- using (FileStream output = File.OpenWrite($"{path}/Rectangle.png"))
- {
- image
- .BackgroundColor(Rgba32.Blue)
- .DrawLines(Rgba32.HotPink, 10, new[] {
+ image
+ .BackgroundColor(Rgba32.Blue)
+ .DrawLines(Rgba32.HotPink, 10, new[] {
new Vector2(10, 10),
new Vector2(200, 10),
new Vector2(200, 150),
new Vector2(10, 150)
- })
- .Save(output);
- }
+ })
+ .Save($"{path}/Rectangle.png");
using (PixelAccessor sourcePixels = image.Lock())
{
diff --git a/tests/ImageSharp.Tests/Drawing/PolygonTests.cs b/tests/ImageSharp.Tests/Drawing/PolygonTests.cs
index 9bc918d37..842fc19d2 100644
--- a/tests/ImageSharp.Tests/Drawing/PolygonTests.cs
+++ b/tests/ImageSharp.Tests/Drawing/PolygonTests.cs
@@ -24,8 +24,6 @@ namespace ImageSharp.Tests.Drawing
using (Image image = new Image(500, 500))
{
- using (FileStream output = File.OpenWrite($"{path}/Simple.png"))
- {
image
.BackgroundColor(Rgba32.Blue)
.DrawPolygon(Rgba32.HotPink, 5,
@@ -34,8 +32,7 @@ namespace ImageSharp.Tests.Drawing
new Vector2(200, 150),
new Vector2(50, 300)
})
- .Save(output);
- }
+ .Save($"{path}/Simple.png");
using (PixelAccessor sourcePixels = image.Lock())
{
@@ -64,13 +61,10 @@ namespace ImageSharp.Tests.Drawing
using (Image