diff --git a/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs b/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs
index cc04d4831..5b4023f0f 100644
--- a/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs
+++ b/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs
@@ -6,8 +6,26 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
/// Provides Gif specific metadata information for the image frame.
///
- public class GifFrameMetaData
+ public class GifFrameMetaData : IDeepCloneable
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public GifFrameMetaData()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The metadata to create an instance from.
+ internal GifFrameMetaData(GifFrameMetaData other)
+ {
+ this.ColorTableLength = other.ColorTableLength;
+ this.FrameDelay = other.FrameDelay;
+ this.DisposalMethod = other.DisposalMethod;
+ }
+
///
/// Gets or sets the length of the color table for paletted images.
/// If not 0, then this field indicates the maximum number of colors to use when quantizing the
@@ -29,5 +47,8 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// be treated after being displayed.
///
public GifDisposalMethod DisposalMethod { get; set; }
+
+ ///
+ public IDeepCloneable DeepClone() => new GifFrameMetaData(this);
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/IDeepCloneable.cs b/src/ImageSharp/IDeepCloneable.cs
new file mode 100644
index 000000000..a792fc044
--- /dev/null
+++ b/src/ImageSharp/IDeepCloneable.cs
@@ -0,0 +1,31 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+namespace SixLabors.ImageSharp
+{
+ ///
+ /// A generic interface for a deeply cloneable type.
+ ///
+ /// The type of object to clone.
+ public interface IDeepCloneable
+ where T : class, IDeepCloneable
+ {
+ ///
+ /// Creates a new that is a deep copy of the current instance.
+ ///
+ /// The .
+ T DeepClone();
+ }
+
+ ///
+ /// An interface for objects that can be cloned. This creates a deep copy of the object.
+ ///
+ public interface IDeepCloneable
+ {
+ ///
+ /// Creates a new object that is a deep copy of the current instance.
+ ///
+ /// The .
+ IDeepCloneable DeepClone();
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/ImageFrame{TPixel}.cs b/src/ImageSharp/ImageFrame{TPixel}.cs
index 132ab598e..dfbae817d 100644
--- a/src/ImageSharp/ImageFrame{TPixel}.cs
+++ b/src/ImageSharp/ImageFrame{TPixel}.cs
@@ -135,7 +135,7 @@ namespace SixLabors.ImageSharp
this.MemoryAllocator = configuration.MemoryAllocator;
this.PixelBuffer = this.MemoryAllocator.Allocate2D(source.PixelBuffer.Width, source.PixelBuffer.Height);
source.PixelBuffer.GetSpan().CopyTo(this.PixelBuffer.GetSpan());
- this.MetaData = source.MetaData.Clone();
+ this.MetaData = source.MetaData.DeepClone();
}
///
@@ -260,7 +260,7 @@ namespace SixLabors.ImageSharp
return this.Clone() as ImageFrame;
}
- var target = new ImageFrame(this.configuration, this.Width, this.Height, this.MetaData.Clone());
+ var target = new ImageFrame(this.configuration, this.Width, this.Height, this.MetaData.DeepClone());
ParallelFor.WithTemporaryBuffer(
0,
diff --git a/src/ImageSharp/MetaData/ImageFrameMetaData.cs b/src/ImageSharp/MetaData/ImageFrameMetaData.cs
index 4b819e201..f1f884be6 100644
--- a/src/ImageSharp/MetaData/ImageFrameMetaData.cs
+++ b/src/ImageSharp/MetaData/ImageFrameMetaData.cs
@@ -1,7 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using System;
using System.Collections.Generic;
using SixLabors.ImageSharp.Formats;
@@ -10,9 +9,9 @@ namespace SixLabors.ImageSharp.MetaData
///
/// Encapsulates the metadata of an image frame.
///
- public sealed class ImageFrameMetaData
+ public sealed class ImageFrameMetaData : IDeepCloneable
{
- private readonly Dictionary formatMetaData = new Dictionary();
+ private readonly Dictionary formatMetaData = new Dictionary();
///
/// Initializes a new instance of the class.
@@ -32,17 +31,14 @@ namespace SixLabors.ImageSharp.MetaData
{
DebugGuard.NotNull(other, nameof(other));
- foreach (KeyValuePair meta in other.formatMetaData)
+ foreach (KeyValuePair meta in other.formatMetaData)
{
- this.formatMetaData.Add(meta.Key, meta.Value);
+ this.formatMetaData.Add(meta.Key, meta.Value.DeepClone());
}
}
- ///
- /// Clones this ImageFrameMetaData.
- ///
- /// The cloned instance.
- public ImageFrameMetaData Clone() => new ImageFrameMetaData(this);
+ ///
+ public ImageFrameMetaData DeepClone() => new ImageFrameMetaData(this);
///
/// Gets the metadata value associated with the specified key.
@@ -55,9 +51,9 @@ namespace SixLabors.ImageSharp.MetaData
///
public TFormatFrameMetaData GetFormatMetaData(IImageFormat key)
where TFormatMetaData : class
- where TFormatFrameMetaData : class
+ where TFormatFrameMetaData : class, IDeepCloneable
{
- if (this.formatMetaData.TryGetValue(key, out object meta))
+ if (this.formatMetaData.TryGetValue(key, out IDeepCloneable meta))
{
return (TFormatFrameMetaData)meta;
}
diff --git a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs
index 3993ab1a8..a7cbb0337 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs
@@ -51,7 +51,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
{
// We will always be creating the clone even for mutate because we may need to resize the canvas
IEnumerable> frames =
- source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.TargetDimensions, x.MetaData.Clone()));
+ source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.TargetDimensions, x.MetaData.DeepClone()));
// Use the overload to prevent an extra frame being added
return new Image(source.GetConfiguration(), source.MetaData.Clone(), frames);
diff --git a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs
index 0c5212375..ab1044df3 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs
@@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
protected override Image CreateDestination(Image source, Rectangle sourceRectangle)
{
// We will always be creating the clone even for mutate because we may need to resize the canvas
- IEnumerable> frames = source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.CropRectangle.Width, this.CropRectangle.Height, x.MetaData.Clone()));
+ IEnumerable> frames = source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.CropRectangle.Width, this.CropRectangle.Height, x.MetaData.DeepClone()));
// Use the overload to prevent an extra frame being added
return new Image(source.GetConfiguration(), source.MetaData.Clone(), frames);
diff --git a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs
index 042ce2ff6..680ce679e 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs
@@ -51,7 +51,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
{
// We will always be creating the clone even for mutate because we may need to resize the canvas
IEnumerable> frames =
- source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.TargetDimensions.Width, this.TargetDimensions.Height, x.MetaData.Clone()));
+ source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.TargetDimensions.Width, this.TargetDimensions.Height, x.MetaData.DeepClone()));
// Use the overload to prevent an extra frame being added
return new Image(source.GetConfiguration(), source.MetaData.Clone(), frames);
diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs
index fd3c34d6c..c3d766622 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs
@@ -215,7 +215,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
protected override Image CreateDestination(Image source, Rectangle sourceRectangle)
{
// We will always be creating the clone even for mutate because we may need to resize the canvas
- IEnumerable> frames = source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.Width, this.Height, x.MetaData.Clone()));
+ IEnumerable> frames = source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.Width, this.Height, x.MetaData.DeepClone()));
// Use the overload to prevent an extra frame being added
return new Image(source.GetConfiguration(), source.MetaData.Clone(), frames);