diff --git a/src/ImageSharp/Formats/Bmp/BmpFormat.cs b/src/ImageSharp/Formats/Bmp/BmpFormat.cs index de3f6f3f4..665f492da 100644 --- a/src/ImageSharp/Formats/Bmp/BmpFormat.cs +++ b/src/ImageSharp/Formats/Bmp/BmpFormat.cs @@ -8,22 +8,30 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Registers the image encoders, decoders and mime type detectors for the bmp format. /// - internal sealed class BmpFormat : ImageFormatBase + internal sealed class BmpFormat : IImageFormat { private BmpFormat() { } + /// + /// Gets the current instance. + /// + public static BmpFormat Instance { get; } = new BmpFormat(); + + /// + public string Name => "BMP"; + /// - public override string Name => "BMP"; + public string DefaultMimeType => "image/bmp"; /// - public override string DefaultMimeType => "image/bmp"; + public IEnumerable MimeTypes => BmpConstants.MimeTypes; /// - public override IEnumerable MimeTypes => BmpConstants.MimeTypes; + public IEnumerable FileExtensions => BmpConstants.FileExtensions; /// - public override IEnumerable FileExtensions => BmpConstants.FileExtensions; + public BmpMetaData CreateDefaultFormatMetaData() => new BmpMetaData(); } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Bmp/BmpMetaData.cs b/src/ImageSharp/Formats/Bmp/BmpMetaData.cs index 1e350200a..aa60f3866 100644 --- a/src/ImageSharp/Formats/Bmp/BmpMetaData.cs +++ b/src/ImageSharp/Formats/Bmp/BmpMetaData.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData; - namespace SixLabors.ImageSharp.Formats.Bmp { /// /// Provides Bmp specific metadata information for the image. /// - public class BmpMetaData : IImageFormatMetaData + public class BmpMetaData { // TODO: Analyse what properties we would like to preserve. } diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index 20f2f1d33..7a880b0f9 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -143,7 +143,7 @@ namespace SixLabors.ImageSharp.Formats.Gif for (int i = 0; i < image.Frames.Count; i++) { ImageFrame frame = image.Frames[i]; - GifFrameMetaData frameMetaData = frame.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); + GifFrameMetaData frameMetaData = frame.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); this.WriteGraphicalControlExtension(frameMetaData, transparencyIndex, stream); this.WriteImageDescriptor(frame, false, stream); @@ -169,7 +169,7 @@ namespace SixLabors.ImageSharp.Formats.Gif GifFrameMetaData previousMeta = null; foreach (ImageFrame frame in image.Frames) { - GifFrameMetaData meta = frame.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); + GifFrameMetaData meta = frame.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); if (quantized is null) { // Allow each frame to be encoded at whatever color depth the frame designates if set. diff --git a/src/ImageSharp/Formats/Gif/GifFormat.cs b/src/ImageSharp/Formats/Gif/GifFormat.cs index 2d14abb44..f91269ced 100644 --- a/src/ImageSharp/Formats/Gif/GifFormat.cs +++ b/src/ImageSharp/Formats/Gif/GifFormat.cs @@ -8,22 +8,33 @@ namespace SixLabors.ImageSharp.Formats.Gif /// /// Registers the image encoders, decoders and mime type detectors for the gif format. /// - internal sealed class GifFormat : ImageFormatBase + internal sealed class GifFormat : IImageFormat { private GifFormat() { } + /// + /// Gets the current instance. + /// + public static GifFormat Instance { get; } = new GifFormat(); + + /// + public string Name => "GIF"; + + /// + public string DefaultMimeType => "image/gif"; + /// - public override string Name => "GIF"; + public IEnumerable MimeTypes => GifConstants.MimeTypes; /// - public override string DefaultMimeType => "image/gif"; + public IEnumerable FileExtensions => GifConstants.FileExtensions; /// - public override IEnumerable MimeTypes => GifConstants.MimeTypes; + public GifMetaData CreateDefaultFormatMetaData() => new GifMetaData(); /// - public override IEnumerable FileExtensions => GifConstants.FileExtensions; + public GifFrameMetaData CreateDefaultFormatFrameMetaData() => new GifFrameMetaData(); } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs b/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs index a7b68e6e8..cc04d4831 100644 --- a/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs +++ b/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData; - namespace SixLabors.ImageSharp.Formats.Gif { /// /// Provides Gif specific metadata information for the image frame. /// - public class GifFrameMetaData : IImageFormatFrameMetaData + public class GifFrameMetaData { /// /// Gets or sets the length of the color table for paletted images. diff --git a/src/ImageSharp/Formats/Gif/GifMetaData.cs b/src/ImageSharp/Formats/Gif/GifMetaData.cs index cc0716ec5..f58f5dff3 100644 --- a/src/ImageSharp/Formats/Gif/GifMetaData.cs +++ b/src/ImageSharp/Formats/Gif/GifMetaData.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData; - namespace SixLabors.ImageSharp.Formats.Gif { /// /// Provides Gif specific metadata information for the image. /// - public class GifMetaData : IImageFormatMetaData + public class GifMetaData { /// /// Gets or sets the number of times any animation is repeated. diff --git a/src/ImageSharp/Formats/IImageFormat.cs b/src/ImageSharp/Formats/IImageFormat.cs index 15bdc73a8..972035275 100644 --- a/src/ImageSharp/Formats/IImageFormat.cs +++ b/src/ImageSharp/Formats/IImageFormat.cs @@ -6,7 +6,37 @@ using System.Collections.Generic; namespace SixLabors.ImageSharp.Formats { /// - /// Describes an image format. + /// Defines the contract for an image format containing metadata with multiple frames. + /// + /// The type of format metadata. + /// The type of format frame metadata. + public interface IImageFormat : IImageFormat + where TFormatMetaData : class + where TFormatFrameMetaData : class + { + /// + /// Creates a default instance of the format frame metadata. + /// + /// The . + TFormatFrameMetaData CreateDefaultFormatFrameMetaData(); + } + + /// + /// Defines the contract for an image format containing metadata. + /// + /// The type of format metadata. + public interface IImageFormat : IImageFormat + where TFormatMetaData : class + { + /// + /// Creates a default instance of the format metadata. + /// + /// The . + TFormatMetaData CreateDefaultFormatMetaData(); + } + + /// + /// Defines the contract for an image format. /// public interface IImageFormat { diff --git a/src/ImageSharp/Formats/ImageFormatBase{T}.cs b/src/ImageSharp/Formats/ImageFormatBase{T}.cs deleted file mode 100644 index 85273db2b..000000000 --- a/src/ImageSharp/Formats/ImageFormatBase{T}.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Collections.Generic; - -namespace SixLabors.ImageSharp.Formats -{ - /// - /// The base class for all image formats. - /// Inheriting classes should implement the singleton pattern by creating a private constructor. - /// - /// The type of image format. - public abstract class ImageFormatBase : IImageFormat - where T : class, IImageFormat - { - private static readonly Lazy Lazy = new Lazy(CreateInstance); - - /// - /// Gets the current instance. - /// - public static T Instance => Lazy.Value; - - /// - public abstract string Name { get; } - - /// - public abstract string DefaultMimeType { get; } - - /// - public abstract IEnumerable MimeTypes { get; } - - /// - public abstract IEnumerable FileExtensions { get; } - - private static T CreateInstance() => (T)Activator.CreateInstance(typeof(T), true); - } -} diff --git a/src/ImageSharp/Formats/Jpeg/JpegFormat.cs b/src/ImageSharp/Formats/Jpeg/JpegFormat.cs index 21757dcb3..94c0895b9 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegFormat.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegFormat.cs @@ -8,22 +8,30 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// /// Registers the image encoders, decoders and mime type detectors for the jpeg format. /// - internal sealed class JpegFormat : ImageFormatBase + internal sealed class JpegFormat : IImageFormat { private JpegFormat() { } + /// + /// Gets the current instance. + /// + public static JpegFormat Instance { get; } = new JpegFormat(); + + /// + public string Name => "JPEG"; + /// - public override string Name => "JPEG"; + public string DefaultMimeType => "image/jpeg"; /// - public override string DefaultMimeType => "image/jpeg"; + public IEnumerable MimeTypes => JpegConstants.MimeTypes; /// - public override IEnumerable MimeTypes => JpegConstants.MimeTypes; + public IEnumerable FileExtensions => JpegConstants.FileExtensions; /// - public override IEnumerable FileExtensions => JpegConstants.FileExtensions; + public JpegMetaData CreateDefaultFormatMetaData() => new JpegMetaData(); } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/JpegMetaData.cs b/src/ImageSharp/Formats/Jpeg/JpegMetaData.cs index eec0efa80..b05f9fa15 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegMetaData.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegMetaData.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData; - namespace SixLabors.ImageSharp.Formats.Jpeg { /// /// Provides Jpeg specific metadata information for the image. /// - public class JpegMetaData : IImageFormatMetaData + public class JpegMetaData { // TODO: Analyse what properties we would like to preserve. } diff --git a/src/ImageSharp/Formats/Png/PngFormat.cs b/src/ImageSharp/Formats/Png/PngFormat.cs index 00ebbde52..b5223cb5a 100644 --- a/src/ImageSharp/Formats/Png/PngFormat.cs +++ b/src/ImageSharp/Formats/Png/PngFormat.cs @@ -8,22 +8,30 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// Registers the image encoders, decoders and mime type detectors for the png format. /// - internal sealed class PngFormat : ImageFormatBase + internal sealed class PngFormat : IImageFormat { private PngFormat() { } + /// + /// Gets the current instance. + /// + public static PngFormat Instance { get; } = new PngFormat(); + + /// + public string Name => "PNG"; + /// - public override string Name => "PNG"; + public string DefaultMimeType => "image/png"; /// - public override string DefaultMimeType => "image/png"; + public IEnumerable MimeTypes => PngConstants.MimeTypes; /// - public override IEnumerable MimeTypes => PngConstants.MimeTypes; + public IEnumerable FileExtensions => PngConstants.FileExtensions; /// - public override IEnumerable FileExtensions => PngConstants.FileExtensions; + public PngMetaData CreateDefaultFormatMetaData() => new PngMetaData(); } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Png/PngMetaData.cs b/src/ImageSharp/Formats/Png/PngMetaData.cs index 1d76cf580..90dbb83b6 100644 --- a/src/ImageSharp/Formats/Png/PngMetaData.cs +++ b/src/ImageSharp/Formats/Png/PngMetaData.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData; - namespace SixLabors.ImageSharp.Formats.Png { /// /// Provides Png specific metadata information for the image. /// - public class PngMetaData : IImageFormatMetaData + public class PngMetaData { // TODO: Analyse what properties we would like to preserve. } diff --git a/src/ImageSharp/MetaData/IImageFormatFrameMetaData.cs b/src/ImageSharp/MetaData/IImageFormatFrameMetaData.cs deleted file mode 100644 index 5df6fa433..000000000 --- a/src/ImageSharp/MetaData/IImageFormatFrameMetaData.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -namespace SixLabors.ImageSharp.MetaData -{ - /// - /// Encapsulates the format specific metadata of an image frame. - /// This interface exists to allow type saftey and avoid the performance overhead of parsing attributes. - /// - public interface IImageFormatFrameMetaData - { - } -} \ No newline at end of file diff --git a/src/ImageSharp/MetaData/IImageFormatMetaData.cs b/src/ImageSharp/MetaData/IImageFormatMetaData.cs deleted file mode 100644 index ded8df801..000000000 --- a/src/ImageSharp/MetaData/IImageFormatMetaData.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -namespace SixLabors.ImageSharp.MetaData -{ - /// - /// Encapsulates the format specific metadata of an image. - /// This interface exists to allow type saftey and avoid the performance overhead of parsing attributes. - /// - public interface IImageFormatMetaData - { - } -} \ No newline at end of file diff --git a/src/ImageSharp/MetaData/ImageFrameMetaData.cs b/src/ImageSharp/MetaData/ImageFrameMetaData.cs index 31bad29b8..07d4bdb05 100644 --- a/src/ImageSharp/MetaData/ImageFrameMetaData.cs +++ b/src/ImageSharp/MetaData/ImageFrameMetaData.cs @@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.MetaData /// public sealed class ImageFrameMetaData { - private readonly Dictionary metaData = new Dictionary(); + private readonly Dictionary metaData = new Dictionary(); /// /// Initializes a new instance of the class. @@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.MetaData { DebugGuard.NotNull(other, nameof(other)); - foreach (KeyValuePair meta in other.metaData) + foreach (KeyValuePair meta in other.metaData) { this.metaData.Add(meta.Key, meta.Value); } @@ -47,12 +47,16 @@ namespace SixLabors.ImageSharp.MetaData /// /// Adds or updates the specified key and value to the . /// + /// The type of format metadata. + /// The type of format frame metadata. /// The key of the metadata to add. /// The value of the element to add. /// key is null. /// value is null. /// An element with the same key already exists in the . - public void AddOrUpdateFormatMetaData(IImageFormat key, IImageFormatFrameMetaData value) + public void AddOrUpdateFormatMetaData(IImageFormat key, TFormatFrameMetaData value) + where TFormatMetaData : class + where TFormatFrameMetaData : class { // Don't think this needs to be threadsafe. Guard.NotNull(value, nameof(value)); @@ -62,20 +66,22 @@ namespace SixLabors.ImageSharp.MetaData /// /// Gets the metadata value associated with the specified key. /// - /// The type of metadata. + /// The type of format metadata. + /// The type of format frame metadata. /// The key of the value to get. /// - /// The . + /// The . /// - public T GetOrAddFormatMetaData(IImageFormat key) - where T : IImageFormatFrameMetaData, new() + public TFormatFrameMetaData GetOrAddFormatMetaData(IImageFormat key) + where TFormatMetaData : class + where TFormatFrameMetaData : class { - if (this.metaData.TryGetValue(key, out IImageFormatFrameMetaData meta)) + if (this.metaData.TryGetValue(key, out object meta)) { - return (T)meta; + return (TFormatFrameMetaData)meta; } - var newMeta = new T(); + TFormatFrameMetaData newMeta = key.CreateDefaultFormatFrameMetaData(); this.AddOrUpdateFormatMetaData(key, newMeta); return newMeta; } diff --git a/src/ImageSharp/MetaData/ImageMetaData.cs b/src/ImageSharp/MetaData/ImageMetaData.cs index d907e8b8a..aa084728c 100644 --- a/src/ImageSharp/MetaData/ImageMetaData.cs +++ b/src/ImageSharp/MetaData/ImageMetaData.cs @@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.MetaData /// public const double DefaultVerticalResolution = 96; - private readonly Dictionary metaData = new Dictionary(); + private readonly Dictionary metaData = new Dictionary(); private double horizontalResolution; private double verticalResolution; @@ -52,7 +52,7 @@ namespace SixLabors.ImageSharp.MetaData this.VerticalResolution = other.VerticalResolution; this.ResolutionUnits = other.ResolutionUnits; - foreach (KeyValuePair meta in other.metaData) + foreach (KeyValuePair meta in other.metaData) { this.metaData.Add(meta.Key, meta.Value); } @@ -134,12 +134,14 @@ namespace SixLabors.ImageSharp.MetaData /// /// Adds or updates the specified key and value to the . /// + /// The type of format metadata. /// The key of the metadata to add. /// The value of the element to add. /// key is null. /// value is null. /// An element with the same key already exists in the . - public void AddOrUpdateFormatMetaData(IImageFormat key, IImageFormatMetaData value) + public void AddOrUpdateFormatMetaData(IImageFormat key, TFormatMetaData value) + where TFormatMetaData : class { // Don't think this needs to be threadsafe. Guard.NotNull(value, nameof(value)); @@ -149,20 +151,20 @@ namespace SixLabors.ImageSharp.MetaData /// /// Gets the metadata value associated with the specified key. /// - /// The type of metadata. + /// The type of metadata. /// The key of the value to get. /// - /// The . + /// The . /// - public T GetOrAddFormatMetaData(IImageFormat key) - where T : IImageFormatMetaData, new() + public TFormatMetaData GetOrAddFormatMetaData(IImageFormat key) + where TFormatMetaData : class { - if (this.metaData.TryGetValue(key, out IImageFormatMetaData meta)) + if (this.metaData.TryGetValue(key, out object meta)) { - return (T)meta; + return (TFormatMetaData)meta; } - var newMeta = new T(); + TFormatMetaData newMeta = key.CreateDefaultFormatMetaData(); this.AddOrUpdateFormatMetaData(key, newMeta); return newMeta; } diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs index 4ddcded5e..0c32689f0 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs @@ -189,8 +189,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif inStream.Position = 0; var image = Image.Load(inStream); - GifMetaData metaData = image.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); - GifFrameMetaData frameMetaData = image.Frames.RootFrame.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); + GifMetaData metaData = image.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); + GifFrameMetaData frameMetaData = image.Frames.RootFrame.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); GifColorTableMode colorMode = metaData.ColorTableMode; var encoder = new GifEncoder() { @@ -212,8 +212,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif for (int i = 0; i < image.Frames.Count; i++) { - GifFrameMetaData ifm = image.Frames[i].MetaData.GetOrAddFormatMetaData(GifFormat.Instance); - GifFrameMetaData cifm = clone.Frames[i].MetaData.GetOrAddFormatMetaData(GifFormat.Instance); + GifFrameMetaData ifm = image.Frames[i].MetaData.GetOrAddFormatMetaData(GifFormat.Instance); + GifFrameMetaData cifm = clone.Frames[i].MetaData.GetOrAddFormatMetaData(GifFormat.Instance); Assert.Equal(ifm.ColorTableLength, cifm.ColorTableLength); Assert.Equal(ifm.FrameDelay, cifm.FrameDelay); diff --git a/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs b/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs index 00d03dce4..54441f0cb 100644 --- a/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs +++ b/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Tests metaData.AddOrUpdateFormatMetaData(GifFormat.Instance, gifFrameMetaData); var clone = new ImageFrameMetaData(metaData); - GifFrameMetaData cloneGifFrameMetaData = clone.GetOrAddFormatMetaData(GifFormat.Instance); + GifFrameMetaData cloneGifFrameMetaData = clone.GetOrAddFormatMetaData(GifFormat.Instance); Assert.Equal(frameDelay, cloneGifFrameMetaData.FrameDelay); Assert.Equal(colorTableLength, cloneGifFrameMetaData.ColorTableLength);