diff --git a/src/ImageSharp/Configuration.cs b/src/ImageSharp/Configuration.cs
index 1b009bfed..354701747 100644
--- a/src/ImageSharp/Configuration.cs
+++ b/src/ImageSharp/Configuration.cs
@@ -125,7 +125,7 @@ namespace SixLabors.ImageSharp
/// Creates a shallow copy of the
///
/// A new configuration instance
- public Configuration ShallowCopy()
+ public Configuration Clone()
{
return new Configuration
{
diff --git a/src/ImageSharp/Formats/Bmp/BmpMetaData.cs b/src/ImageSharp/Formats/Bmp/BmpMetaData.cs
index 3d678c13e..8b33e30fa 100644
--- a/src/ImageSharp/Formats/Bmp/BmpMetaData.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpMetaData.cs
@@ -6,13 +6,29 @@ namespace SixLabors.ImageSharp.Formats.Bmp
///
/// Provides Bmp specific metadata information for the image.
///
- public class BmpMetaData
+ public class BmpMetaData : IDeepCloneable
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public BmpMetaData()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The metadata to create an instance from.
+ private BmpMetaData(BmpMetaData other) => this.BitsPerPixel = other.BitsPerPixel;
+
///
/// Gets or sets the number of bits per pixel.
///
public BmpBitsPerPixel BitsPerPixel { get; set; } = BmpBitsPerPixel.Pixel24;
+ ///
+ public IDeepCloneable DeepClone() => new BmpMetaData(this);
+
// TODO: Colors used once we support encoding palette bmps.
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs b/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs
index cc04d4831..0042c6a10 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.
+ private 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/Formats/Gif/GifMetaData.cs b/src/ImageSharp/Formats/Gif/GifMetaData.cs
index f58f5dff3..bb7fb5051 100644
--- a/src/ImageSharp/Formats/Gif/GifMetaData.cs
+++ b/src/ImageSharp/Formats/Gif/GifMetaData.cs
@@ -6,8 +6,26 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
/// Provides Gif specific metadata information for the image.
///
- public class GifMetaData
+ public class GifMetaData : IDeepCloneable
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public GifMetaData()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The metadata to create an instance from.
+ private GifMetaData(GifMetaData other)
+ {
+ this.RepeatCount = other.RepeatCount;
+ this.ColorTableMode = other.ColorTableMode;
+ this.GlobalColorTableLength = other.GlobalColorTableLength;
+ }
+
///
/// Gets or sets the number of times any animation is repeated.
///
@@ -25,5 +43,8 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// Gets or sets the length of the global color table if present.
///
public int GlobalColorTableLength { get; set; }
+
+ ///
+ public IDeepCloneable DeepClone() => new GifMetaData(this);
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/JpegMetaData.cs b/src/ImageSharp/Formats/Jpeg/JpegMetaData.cs
index bd7232e60..fcad29e5d 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegMetaData.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegMetaData.cs
@@ -6,11 +6,27 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
///
/// Provides Jpeg specific metadata information for the image.
///
- public class JpegMetaData
+ public class JpegMetaData : IDeepCloneable
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public JpegMetaData()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The metadata to create an instance from.
+ private JpegMetaData(JpegMetaData other) => this.Quality = other.Quality;
+
///
/// Gets or sets the encoded quality.
///
public int Quality { get; set; } = 75;
+
+ ///
+ public IDeepCloneable DeepClone() => new JpegMetaData(this);
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Png/PngMetaData.cs b/src/ImageSharp/Formats/Png/PngMetaData.cs
index 1eb3cdad6..9c7676514 100644
--- a/src/ImageSharp/Formats/Png/PngMetaData.cs
+++ b/src/ImageSharp/Formats/Png/PngMetaData.cs
@@ -6,8 +6,26 @@ namespace SixLabors.ImageSharp.Formats.Png
///
/// Provides Png specific metadata information for the image.
///
- public class PngMetaData
+ public class PngMetaData : IDeepCloneable
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public PngMetaData()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The metadata to create an instance from.
+ private PngMetaData(PngMetaData other)
+ {
+ this.BitDepth = other.BitDepth;
+ this.ColorType = other.ColorType;
+ this.Gamma = other.Gamma;
+ }
+
///
/// Gets or sets the number of bits per sample or per palette index (not per pixel).
/// Not all values are allowed for all values.
@@ -23,5 +41,8 @@ namespace SixLabors.ImageSharp.Formats.Png
/// Gets or sets the gamma value for the image.
///
public float Gamma { get; set; }
+
+ ///
+ public IDeepCloneable DeepClone() => new PngMetaData(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..f80247a5d
--- /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
+ {
+ ///
+ /// 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/ImageFrameCollection.cs b/src/ImageSharp/ImageFrameCollection.cs
index 59571ce92..bbe05ce43 100644
--- a/src/ImageSharp/ImageFrameCollection.cs
+++ b/src/ImageSharp/ImageFrameCollection.cs
@@ -94,7 +94,7 @@ namespace SixLabors.ImageSharp
public ImageFrame InsertFrame(int index, ImageFrame source)
{
this.ValidateFrame(source);
- ImageFrame clonedFrame = source.Clone();
+ ImageFrame clonedFrame = source.Clone(this.parent.GetConfiguration());
this.frames.Insert(index, clonedFrame);
return clonedFrame;
}
@@ -107,7 +107,7 @@ namespace SixLabors.ImageSharp
public ImageFrame AddFrame(ImageFrame source)
{
this.ValidateFrame(source);
- ImageFrame clonedFrame = source.Clone();
+ ImageFrame clonedFrame = source.Clone(this.parent.GetConfiguration());
this.frames.Add(clonedFrame);
return clonedFrame;
}
@@ -155,10 +155,7 @@ namespace SixLabors.ImageSharp
///
/// true if the contains the specified frame; otherwise, false.
///
- public bool Contains(ImageFrame frame)
- {
- return this.frames.Contains(frame);
- }
+ public bool Contains(ImageFrame frame) => this.frames.Contains(frame);
///
/// Moves an from to .
@@ -195,7 +192,7 @@ namespace SixLabors.ImageSharp
this.frames.Remove(frame);
- return new Image(this.parent.GetConfiguration(), this.parent.MetaData.Clone(), new[] { frame });
+ return new Image(this.parent.GetConfiguration(), this.parent.MetaData.DeepClone(), new[] { frame });
}
///
@@ -208,7 +205,7 @@ namespace SixLabors.ImageSharp
{
ImageFrame frame = this[index];
ImageFrame clonedFrame = frame.Clone();
- return new Image(this.parent.GetConfiguration(), this.parent.MetaData.Clone(), new[] { clonedFrame });
+ return new Image(this.parent.GetConfiguration(), this.parent.MetaData.DeepClone(), new[] { clonedFrame });
}
///
@@ -217,10 +214,7 @@ namespace SixLabors.ImageSharp
///
/// The new .
///
- public ImageFrame CreateFrame()
- {
- return this.CreateFrame(default);
- }
+ public ImageFrame CreateFrame() => this.CreateFrame(default);
///
/// Creates a new and appends it to the end of the collection.
diff --git a/src/ImageSharp/ImageFrame{TPixel}.cs b/src/ImageSharp/ImageFrame{TPixel}.cs
index 132ab598e..5f1aa5a38 100644
--- a/src/ImageSharp/ImageFrame{TPixel}.cs
+++ b/src/ImageSharp/ImageFrame{TPixel}.cs
@@ -95,6 +95,10 @@ namespace SixLabors.ImageSharp
///
/// Initializes a new instance of the class wrapping an existing buffer.
///
+ /// The configuration providing initialization code which allows extending the library.
+ /// The width of the image in pixels.
+ /// The height of the image in pixels.
+ /// The memory source.
internal ImageFrame(Configuration configuration, int width, int height, MemorySource memorySource)
: this(configuration, width, height, memorySource, new ImageFrameMetaData())
{
@@ -103,12 +107,12 @@ namespace SixLabors.ImageSharp
///
/// Initializes a new instance of the class wrapping an existing buffer.
///
- internal ImageFrame(
- Configuration configuration,
- int width,
- int height,
- MemorySource memorySource,
- ImageFrameMetaData metaData)
+ /// The configuration providing initialization code which allows extending the library.
+ /// The width of the image in pixels.
+ /// The height of the image in pixels.
+ /// The memory source.
+ /// The meta data.
+ internal ImageFrame(Configuration configuration, int width, int height, MemorySource memorySource, ImageFrameMetaData metaData)
{
Guard.NotNull(configuration, nameof(configuration));
Guard.MustBeGreaterThan(width, 0, nameof(width));
@@ -135,7 +139,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();
}
///
@@ -247,25 +251,47 @@ namespace SixLabors.ImageSharp
///
public override string ToString() => $"ImageFrame<{typeof(TPixel).Name}>: {this.Width}x{this.Height}";
+ ///
+ /// Clones the current instance.
+ ///
+ /// The
+ internal ImageFrame Clone() => this.Clone(this.configuration);
+
+ ///
+ /// Clones the current instance.
+ ///
+ /// The configuration providing initialization code which allows extending the library.
+ /// The
+ internal ImageFrame Clone(Configuration configuration) => new ImageFrame(configuration, this);
+
///
/// Returns a copy of the image frame in the given pixel format.
///
/// The pixel format.
/// The
internal ImageFrame CloneAs()
+ where TPixel2 : struct, IPixel => this.CloneAs(this.configuration);
+
+ ///
+ /// Returns a copy of the image frame in the given pixel format.
+ ///
+ /// The pixel format.
+ /// The configuration providing initialization code which allows extending the library.
+ /// The
+ internal ImageFrame CloneAs(Configuration configuration)
where TPixel2 : struct, IPixel
{
if (typeof(TPixel2) == typeof(TPixel))
{
- return this.Clone() as ImageFrame;
+ return this.Clone(configuration) as ImageFrame;
}
- var target = new ImageFrame(this.configuration, this.Width, this.Height, this.MetaData.Clone());
+ var target = new ImageFrame(configuration, this.Width, this.Height, this.MetaData.DeepClone());
ParallelFor.WithTemporaryBuffer(
0,
this.Height,
- this.configuration,
+ configuration,
this.Width,
(int y, IMemoryOwner tempRowBuffer) =>
{
@@ -298,12 +324,6 @@ namespace SixLabors.ImageSharp
});
}
- ///
- /// Clones the current instance.
- ///
- /// The
- internal ImageFrame Clone() => new ImageFrame(this.configuration, this);
-
///
void IDisposable.Dispose() => this.Dispose();
}
diff --git a/src/ImageSharp/Image{TPixel}.cs b/src/ImageSharp/Image{TPixel}.cs
index 8bc5a40bd..9d4c1ef0b 100644
--- a/src/ImageSharp/Image{TPixel}.cs
+++ b/src/ImageSharp/Image{TPixel}.cs
@@ -11,7 +11,6 @@ using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.Memory;
namespace SixLabors.ImageSharp
{
@@ -23,15 +22,12 @@ namespace SixLabors.ImageSharp
where TPixel : struct, IPixel
{
private readonly Configuration configuration;
- private readonly ImageFrameCollection frames;
///
/// Initializes a new instance of the class
/// with the height and the width of the image.
///
- ///
- /// The configuration providing initialization code which allows extending the library.
- ///
+ /// The configuration providing initialization code which allows extending the library.
/// The width of the image in pixels.
/// The height of the image in pixels.
public Image(Configuration configuration, int width, int height)
@@ -43,9 +39,7 @@ namespace SixLabors.ImageSharp
/// Initializes a new instance of the class
/// with the height and the width of the image.
///
- ///
- /// The configuration providing initialization code which allows extending the library.
- ///
+ /// The configuration providing initialization code which allows extending the library.
/// The width of the image in pixels.
/// The height of the image in pixels.
/// The color to initialize the pixels with.
@@ -69,9 +63,7 @@ namespace SixLabors.ImageSharp
/// Initializes a new instance of the class
/// with the height and the width of the image.
///
- ///
- /// The configuration providing initialization code which allows extending the library.
- ///
+ /// The configuration providing initialization code which allows extending the library.
/// The width of the image in pixels.
/// The height of the image in pixels.
/// The images metadata.
@@ -80,37 +72,41 @@ namespace SixLabors.ImageSharp
this.configuration = configuration ?? Configuration.Default;
this.PixelType = new PixelTypeInfo(Unsafe.SizeOf() * 8);
this.MetaData = metadata ?? new ImageMetaData();
- this.frames = new ImageFrameCollection(this, width, height, default(TPixel));
+ this.Frames = new ImageFrameCollection(this, width, height, default(TPixel));
}
///
/// Initializes a new instance of the class
/// wrapping an external
///
+ /// The configuration providing initialization code which allows extending the library.
+ /// The memory source.
+ /// The width of the image in pixels.
+ /// The height of the image in pixels.
+ /// The images metadata.
internal Image(Configuration configuration, MemorySource memorySource, int width, int height, ImageMetaData metadata)
{
this.configuration = configuration;
this.PixelType = new PixelTypeInfo(Unsafe.SizeOf() * 8);
this.MetaData = metadata;
- this.frames = new ImageFrameCollection(this, width, height, memorySource);
+ this.Frames = new ImageFrameCollection(this, width, height, memorySource);
}
///
/// Initializes a new instance of the class
/// with the height and the width of the image.
///
- ///
- /// The configuration providing initialization code which allows extending the library.
- ///
+ /// The configuration providing initialization code which allows extending the library.
/// The width of the image in pixels.
/// The height of the image in pixels.
/// The color to initialize the pixels with.
/// The images metadata.
- internal Image(Configuration configuration, int width, int height, TPixel backgroundColor, ImageMetaData metadata) {
+ internal Image(Configuration configuration, int width, int height, TPixel backgroundColor, ImageMetaData metadata)
+ {
this.configuration = configuration ?? Configuration.Default;
this.PixelType = new PixelTypeInfo(Unsafe.SizeOf() * 8);
this.MetaData = metadata ?? new ImageMetaData();
- this.frames = new ImageFrameCollection(this, width, height, backgroundColor);
+ this.Frames = new ImageFrameCollection(this, width, height, backgroundColor);
}
///
@@ -126,7 +122,7 @@ namespace SixLabors.ImageSharp
this.PixelType = new PixelTypeInfo(Unsafe.SizeOf() * 8);
this.MetaData = metadata ?? new ImageMetaData();
- this.frames = new ImageFrameCollection(this, frames);
+ this.Frames = new ImageFrameCollection(this, frames);
}
///
@@ -138,10 +134,10 @@ namespace SixLabors.ImageSharp
public PixelTypeInfo PixelType { get; }
///
- public int Width => this.frames.RootFrame.Width;
+ public int Width => this.Frames.RootFrame.Width;
///
- public int Height => this.frames.RootFrame.Height;
+ public int Height => this.Frames.RootFrame.Height;
///
public ImageMetaData MetaData { get; }
@@ -149,12 +145,12 @@ namespace SixLabors.ImageSharp
///
/// Gets the frames.
///
- public ImageFrameCollection Frames => this.frames;
+ public ImageFrameCollection Frames { get; }
///
/// Gets the root frame.
///
- private IPixelSource PixelSource => this.frames?.RootFrame ?? throw new ObjectDisposedException(nameof(Image));
+ private IPixelSource PixelSource => this.Frames?.RootFrame ?? throw new ObjectDisposedException(nameof(Image));
///
/// Gets or sets the pixel at the specified position.
@@ -187,16 +183,17 @@ namespace SixLabors.ImageSharp
/// Clones the current image
///
/// Returns a new image with all the same metadata as the original.
- public Image Clone()
- {
- IEnumerable> clonedFrames = this.frames.Select(x => x.Clone());
- return new Image(this.configuration, this.MetaData.Clone(), clonedFrames);
- }
+ public Image Clone() => this.Clone(this.configuration);
- ///
- public override string ToString()
+ ///
+ /// Clones the current image with the given configueation.
+ ///
+ /// The configuration providing initialization code which allows extending the library.
+ /// Returns a new with all the same pixel data as the original.
+ public Image Clone(Configuration configuration)
{
- return $"Image<{typeof(TPixel).Name}>: {this.Width}x{this.Height}";
+ IEnumerable> clonedFrames = this.Frames.Select(x => x.Clone(configuration));
+ return new Image(configuration, this.MetaData.DeepClone(), clonedFrames);
}
///
@@ -205,22 +202,27 @@ namespace SixLabors.ImageSharp
/// The pixel format.
/// The
public Image CloneAs()
- where TPixel2 : struct, IPixel
- {
- IEnumerable> clonedFrames = this.frames.Select(x => x.CloneAs());
- var target = new Image(this.configuration, this.MetaData.Clone(), clonedFrames);
-
- return target;
- }
+ where TPixel2 : struct, IPixel => this.CloneAs(this.configuration);
///
- /// Releases managed resources.
+ /// Returns a copy of the image in the given pixel format.
///
- public void Dispose()
+ /// The pixel format.
+ /// The configuration providing initialization code which allows extending the library.
+ /// The
+ public Image CloneAs(Configuration configuration)
+ where TPixel2 : struct, IPixel
{
- this.frames.Dispose();
+ IEnumerable> clonedFrames = this.Frames.Select(x => x.CloneAs(configuration));
+ return new Image(configuration, this.MetaData.DeepClone(), clonedFrames);
}
+ ///
+ public void Dispose() => this.Frames.Dispose();
+
+ ///
+ public override string ToString() => $"Image<{typeof(TPixel).Name}>: {this.Width}x{this.Height}";
+
///
/// Switches the buffers used by the image and the pixelSource meaning that the Image will "own" the buffer from the pixelSource and the pixelSource will now own the Images buffer.
///
@@ -229,9 +231,9 @@ namespace SixLabors.ImageSharp
{
Guard.NotNull(pixelSource, nameof(pixelSource));
- for (int i = 0; i < this.frames.Count; i++)
+ for (int i = 0; i < this.Frames.Count; i++)
{
- this.frames[i].SwapOrCopyPixelsBufferFrom(pixelSource.frames[i]);
+ this.Frames[i].SwapOrCopyPixelsBufferFrom(pixelSource.Frames[i]);
}
}
}
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/MetaData/ImageMetaData.cs b/src/ImageSharp/MetaData/ImageMetaData.cs
index 7e74157e7..73549d98a 100644
--- a/src/ImageSharp/MetaData/ImageMetaData.cs
+++ b/src/ImageSharp/MetaData/ImageMetaData.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;
using SixLabors.ImageSharp.MetaData.Profiles.Exif;
@@ -12,7 +11,7 @@ namespace SixLabors.ImageSharp.MetaData
///
/// Encapsulates the metadata of an image.
///
- public sealed class ImageMetaData
+ public sealed class ImageMetaData : IDeepCloneable
{
///
/// The default horizontal resolution value (dots per inch) in x direction.
@@ -26,7 +25,13 @@ namespace SixLabors.ImageSharp.MetaData
///
public const double DefaultVerticalResolution = 96;
- private readonly Dictionary formatMetaData = new Dictionary();
+ ///
+ /// The default pixel resolution units.
+ /// The default value is .
+ ///
+ public const PixelResolutionUnit DefaultPixelResolutionUnits = PixelResolutionUnit.PixelsPerInch;
+
+ private readonly Dictionary formatMetaData = new Dictionary();
private double horizontalResolution;
private double verticalResolution;
@@ -37,6 +42,7 @@ namespace SixLabors.ImageSharp.MetaData
{
this.horizontalResolution = DefaultHorizontalResolution;
this.verticalResolution = DefaultVerticalResolution;
+ this.ResolutionUnits = DefaultPixelResolutionUnits;
}
///
@@ -52,9 +58,9 @@ namespace SixLabors.ImageSharp.MetaData
this.VerticalResolution = other.VerticalResolution;
this.ResolutionUnits = other.ResolutionUnits;
- 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());
}
foreach (ImageProperty property in other.Properties)
@@ -62,13 +68,8 @@ namespace SixLabors.ImageSharp.MetaData
this.Properties.Add(property);
}
- this.ExifProfile = other.ExifProfile != null
- ? new ExifProfile(other.ExifProfile)
- : null;
-
- this.IccProfile = other.IccProfile != null
- ? new IccProfile(other.IccProfile)
- : null;
+ this.ExifProfile = other.ExifProfile?.DeepClone();
+ this.IccProfile = other.IccProfile?.DeepClone();
}
///
@@ -114,7 +115,7 @@ namespace SixLabors.ImageSharp.MetaData
/// 02 : Pixels per centimeter
/// 03 : Pixels per meter
///
- public PixelResolutionUnit ResolutionUnits { get; set; } = PixelResolutionUnit.PixelsPerInch;
+ public PixelResolutionUnit ResolutionUnits { get; set; }
///
/// Gets or sets the Exif profile.
@@ -140,9 +141,9 @@ namespace SixLabors.ImageSharp.MetaData
/// The .
///
public TFormatMetaData GetFormatMetaData(IImageFormat key)
- where TFormatMetaData : class
+ where TFormatMetaData : class, IDeepCloneable
{
- if (this.formatMetaData.TryGetValue(key, out object meta))
+ if (this.formatMetaData.TryGetValue(key, out IDeepCloneable meta))
{
return (TFormatMetaData)meta;
}
@@ -152,11 +153,8 @@ namespace SixLabors.ImageSharp.MetaData
return newMeta;
}
- ///
- /// Clones this into a new instance
- ///
- /// The cloned metadata instance
- public ImageMetaData Clone() => new ImageMetaData(this);
+ ///
+ public ImageMetaData DeepClone() => new ImageMetaData(this);
///
/// Looks up a property with the provided name.
diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifProfile.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifProfile.cs
index 1dd885721..b48b146f1 100644
--- a/src/ImageSharp/MetaData/Profiles/Exif/ExifProfile.cs
+++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifProfile.cs
@@ -12,23 +12,18 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
///
/// Represents an EXIF profile providing access to the collection of values.
///
- public sealed class ExifProfile
+ public sealed class ExifProfile : IDeepCloneable
{
///
/// The byte array to read the EXIF profile from.
///
- private byte[] data;
+ private readonly byte[] data;
///
/// The collection of EXIF values
///
private List values;
- ///
- /// The list of invalid EXIF tags
- ///
- private IReadOnlyList invalidTags;
-
///
/// The thumbnail offset position in the byte stream
///
@@ -55,7 +50,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
{
this.Parts = ExifParts.All;
this.data = data;
- this.invalidTags = new List();
+ this.InvalidTags = new List();
}
///
@@ -63,22 +58,19 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
/// by making a copy from another EXIF profile.
///
/// The other EXIF profile, where the clone should be made from.
- /// is null.
- public ExifProfile(ExifProfile other)
+ private ExifProfile(ExifProfile other)
{
- Guard.NotNull(other, nameof(other));
-
this.Parts = other.Parts;
this.thumbnailLength = other.thumbnailLength;
this.thumbnailOffset = other.thumbnailOffset;
- this.invalidTags = new List(other.invalidTags);
+ this.InvalidTags = new List(other.InvalidTags);
if (other.values != null)
{
this.values = new List(other.Values.Count);
foreach (ExifValue value in other.Values)
{
- this.values.Add(new ExifValue(value));
+ this.values.Add(value.DeepClone());
}
}
@@ -97,7 +89,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
///
/// Gets the tags that where found but contained an invalid value.
///
- public IReadOnlyList InvalidTags => this.invalidTags;
+ public IReadOnlyList InvalidTags { get; private set; }
///
/// Gets the values of this EXIF profile.
@@ -249,6 +241,9 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
return writer.GetData();
}
+ ///
+ public ExifProfile DeepClone() => new ExifProfile(this);
+
///
/// Synchronizes the profiles with the specified meta data.
///
@@ -294,7 +289,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
this.values = reader.ReadValues();
- this.invalidTags = new List(reader.InvalidTags);
+ this.InvalidTags = new List(reader.InvalidTags);
this.thumbnailOffset = (int)reader.ThumbnailOffset;
this.thumbnailLength = (int)reader.ThumbnailLength;
}
diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs
index e6da9b7d1..ccacfd0bf 100644
--- a/src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs
+++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs
@@ -11,15 +11,30 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
///
/// Represent the value of the EXIF profile.
///
- public sealed class ExifValue : IEquatable
+ public sealed class ExifValue : IEquatable, IDeepCloneable
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The tag.
+ /// The data type.
+ /// The value.
+ /// Whether the value is an array.
+ internal ExifValue(ExifTag tag, ExifDataType dataType, object value, bool isArray)
+ {
+ this.Tag = tag;
+ this.DataType = dataType;
+ this.IsArray = isArray && dataType != ExifDataType.Ascii;
+ this.Value = value;
+ }
+
///
/// Initializes a new instance of the class
/// by making a copy from another exif value.
///
/// The other exif value, where the clone should be made from.
- /// is null.
- public ExifValue(ExifValue other)
+ /// is null.
+ private ExifValue(ExifValue other)
{
Guard.NotNull(other, nameof(other));
@@ -29,30 +44,17 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
if (!other.IsArray)
{
+ // All types are value types except for string which is immutable so safe to simply assign.
this.Value = other.Value;
}
else
{
+ // All array types are value types so Clone() is sufficient here.
var array = (Array)other.Value;
this.Value = array.Clone();
}
}
- ///
- /// Initializes a new instance of the class.
- ///
- /// The tag.
- /// The data type.
- /// The value.
- /// Whether the value is an array.
- internal ExifValue(ExifTag tag, ExifDataType dataType, object value, bool isArray)
- {
- this.Tag = tag;
- this.DataType = dataType;
- this.IsArray = isArray && dataType != ExifDataType.Ascii;
- this.Value = value;
- }
-
///
/// Gets the data type of the exif value.
///
@@ -145,10 +147,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
///
/// True if the parameter is equal to the parameter; otherwise, false.
///
- public static bool operator ==(ExifValue left, ExifValue right)
- {
- return ReferenceEquals(left, right) || left.Equals(right);
- }
+ public static bool operator ==(ExifValue left, ExifValue right) => ReferenceEquals(left, right) || left.Equals(right);
///
/// Compares two objects for equality.
@@ -162,16 +161,10 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
///
/// True if the parameter is not equal to the parameter; otherwise, false.
///
- public static bool operator !=(ExifValue left, ExifValue right)
- {
- return !(left == right);
- }
+ public static bool operator !=(ExifValue left, ExifValue right) => !(left == right);
///
- public override bool Equals(object obj)
- {
- return obj is ExifValue other && this.Equals(other);
- }
+ public override bool Equals(object obj) => obj is ExifValue other && this.Equals(other);
///
public bool Equals(ExifValue other)
@@ -187,9 +180,9 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
}
return
- this.Tag == other.Tag &&
- this.DataType == other.DataType &&
- object.Equals(this.Value, other.Value);
+ this.Tag == other.Tag
+ && this.DataType == other.DataType
+ && object.Equals(this.Value, other.Value);
}
///
@@ -205,10 +198,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
}
///
- public override int GetHashCode()
- {
- return this.GetHashCode(this);
- }
+ public override int GetHashCode() => this.GetHashCode(this);
///
public override string ToString()
@@ -238,6 +228,9 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
return sb.ToString();
}
+ ///
+ public ExifValue DeepClone() => new ExifValue(this);
+
///
/// Creates a new
///
@@ -584,7 +577,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
private static ExifValue CreateNumber(ExifTag tag, object value, bool isArray)
{
Type type = value?.GetType();
- if (type != null && type.IsArray)
+ if (type?.IsArray == true)
{
type = type.GetElementType();
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs b/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs
index dac56c608..44990b7ec 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs
@@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
/// Represents an ICC profile
///
- public sealed class IccProfile
+ public sealed class IccProfile : IDeepCloneable
{
///
/// The byte array to read the ICC profile from
@@ -42,23 +42,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// Initializes a new instance of the class.
///
/// The raw ICC profile data
- public IccProfile(byte[] data)
- {
- this.data = data;
- }
-
- ///
- /// Initializes a new instance of the class
- /// by making a copy from another ICC profile.
- ///
- /// The other ICC profile, where the clone should be made from.
- /// is null.>
- public IccProfile(IccProfile other)
- {
- Guard.NotNull(other, nameof(other));
-
- this.data = other.ToByteArray();
- }
+ public IccProfile(byte[] data) => this.data = data;
///
/// Initializes a new instance of the class.
@@ -74,6 +58,19 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
this.entries = new List(entries);
}
+ ///
+ /// Initializes a new instance of the class
+ /// by making a copy from another ICC profile.
+ ///
+ /// The other ICC profile, where the clone should be made from.
+ /// is null.>
+ private IccProfile(IccProfile other)
+ {
+ Guard.NotNull(other, nameof(other));
+
+ this.data = other.ToByteArray();
+ }
+
///
/// Gets or sets the profile header
///
@@ -100,6 +97,9 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
}
+ ///
+ public IccProfile DeepClone() => new IccProfile(this);
+
#if !NETSTANDARD1_1
///
diff --git a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs
index 3993ab1a8..a7e158925 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs
@@ -51,10 +51,10 @@ 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);
+ return new Image(source.GetConfiguration(), source.MetaData.DeepClone(), frames);
}
///
diff --git a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs
index 0c5212375..df1ac3274 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs
@@ -36,10 +36,10 @@ 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);
+ return new Image(source.GetConfiguration(), source.MetaData.DeepClone(), frames);
}
///
diff --git a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs
index 042ce2ff6..15816cb4d 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs
@@ -51,10 +51,10 @@ 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);
+ return new Image(source.GetConfiguration(), source.MetaData.DeepClone(), frames);
}
///
diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs
index fd3c34d6c..b1c0632c6 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs
@@ -215,10 +215,10 @@ 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);
+ return new Image(source.GetConfiguration(), source.MetaData.DeepClone(), frames);
}
///
diff --git a/tests/ImageSharp.Tests/ConfigurationTests.cs b/tests/ImageSharp.Tests/ConfigurationTests.cs
index 6a8479b2b..963d67446 100644
--- a/tests/ImageSharp.Tests/ConfigurationTests.cs
+++ b/tests/ImageSharp.Tests/ConfigurationTests.cs
@@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Tests
{
// the shallow copy of configuration should behave exactly like the default configuration,
// so by using the copy, we test both the default and the copy.
- this.DefaultConfiguration = Configuration.CreateDefaultInstance().ShallowCopy();
+ this.DefaultConfiguration = Configuration.CreateDefaultInstance().Clone();
this.ConfigurationEmpty = new Configuration();
}
diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpMetaDataTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpMetaDataTests.cs
new file mode 100644
index 000000000..991768a11
--- /dev/null
+++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpMetaDataTests.cs
@@ -0,0 +1,22 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using SixLabors.ImageSharp.Formats.Bmp;
+using Xunit;
+
+namespace SixLabors.ImageSharp.Tests.Formats.Bmp
+{
+ public class BmpMetaDataTests
+ {
+ [Fact]
+ public void CloneIsDeep()
+ {
+ var meta = new BmpMetaData() { BitsPerPixel = BmpBitsPerPixel.Pixel24 };
+ var clone = (BmpMetaData)meta.DeepClone();
+
+ clone.BitsPerPixel = BmpBitsPerPixel.Pixel32;
+
+ Assert.False(meta.BitsPerPixel.Equals(clone.BitsPerPixel));
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifFrameMetaDataTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifFrameMetaDataTests.cs
new file mode 100644
index 000000000..a39fc47b4
--- /dev/null
+++ b/tests/ImageSharp.Tests/Formats/Gif/GifFrameMetaDataTests.cs
@@ -0,0 +1,32 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using SixLabors.ImageSharp.Formats.Gif;
+using Xunit;
+
+namespace SixLabors.ImageSharp.Tests.Formats.Gif
+{
+ public class GifFrameMetaDataTests
+ {
+ [Fact]
+ public void CloneIsDeep()
+ {
+ var meta = new GifFrameMetaData()
+ {
+ FrameDelay = 1,
+ DisposalMethod = GifDisposalMethod.RestoreToBackground,
+ ColorTableLength = 2
+ };
+
+ var clone = (GifFrameMetaData)meta.DeepClone();
+
+ clone.FrameDelay = 2;
+ clone.DisposalMethod = GifDisposalMethod.RestoreToPrevious;
+ clone.ColorTableLength = 1;
+
+ Assert.False(meta.FrameDelay.Equals(clone.FrameDelay));
+ Assert.False(meta.DisposalMethod.Equals(clone.DisposalMethod));
+ Assert.False(meta.ColorTableLength.Equals(clone.ColorTableLength));
+ }
+ }
+}
diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifMetaDataTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifMetaDataTests.cs
new file mode 100644
index 000000000..29db32b4a
--- /dev/null
+++ b/tests/ImageSharp.Tests/Formats/Gif/GifMetaDataTests.cs
@@ -0,0 +1,32 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using SixLabors.ImageSharp.Formats.Gif;
+using Xunit;
+
+namespace SixLabors.ImageSharp.Tests.Formats.Gif
+{
+ public class GifMetaDataTests
+ {
+ [Fact]
+ public void CloneIsDeep()
+ {
+ var meta = new GifMetaData()
+ {
+ RepeatCount = 1,
+ ColorTableMode = GifColorTableMode.Global,
+ GlobalColorTableLength = 2
+ };
+
+ var clone = (GifMetaData)meta.DeepClone();
+
+ clone.RepeatCount = 2;
+ clone.ColorTableMode = GifColorTableMode.Local;
+ clone.GlobalColorTableLength = 1;
+
+ Assert.False(meta.RepeatCount.Equals(clone.RepeatCount));
+ Assert.False(meta.ColorTableMode.Equals(clone.ColorTableMode));
+ Assert.False(meta.GlobalColorTableLength.Equals(clone.GlobalColorTableLength));
+ }
+ }
+}
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegMetaDataTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegMetaDataTests.cs
new file mode 100644
index 000000000..431de4be3
--- /dev/null
+++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegMetaDataTests.cs
@@ -0,0 +1,22 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using SixLabors.ImageSharp.Formats.Jpeg;
+using Xunit;
+
+namespace SixLabors.ImageSharp.Tests.Formats.Jpg
+{
+ public class JpegMetaDataTests
+ {
+ [Fact]
+ public void CloneIsDeep()
+ {
+ var meta = new JpegMetaData() { Quality = 50 };
+ var clone = (JpegMetaData)meta.DeepClone();
+
+ clone.Quality = 99;
+
+ Assert.False(meta.Quality.Equals(clone.Quality));
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Formats/Png/PngMetaDataTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngMetaDataTests.cs
new file mode 100644
index 000000000..a21bb9acb
--- /dev/null
+++ b/tests/ImageSharp.Tests/Formats/Png/PngMetaDataTests.cs
@@ -0,0 +1,31 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using SixLabors.ImageSharp.Formats.Png;
+using Xunit;
+
+namespace SixLabors.ImageSharp.Tests.Formats.Png
+{
+ public class PngMetaDataTests
+ {
+ [Fact]
+ public void CloneIsDeep()
+ {
+ var meta = new PngMetaData()
+ {
+ BitDepth = PngBitDepth.Bit16,
+ ColorType = PngColorType.GrayscaleWithAlpha,
+ Gamma = 2
+ };
+ var clone = (PngMetaData)meta.DeepClone();
+
+ clone.BitDepth = PngBitDepth.Bit2;
+ clone.ColorType = PngColorType.Palette;
+ clone.Gamma = 1;
+
+ Assert.False(meta.BitDepth.Equals(clone.BitDepth));
+ Assert.False(meta.ColorType.Equals(clone.ColorType));
+ Assert.False(meta.Gamma.Equals(clone.Gamma));
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs b/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs
index 69572425c..16d999ad2 100644
--- a/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs
+++ b/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs
@@ -84,7 +84,7 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
public void WrapMemory_CreatedImageIsCorrect()
{
- Configuration cfg = Configuration.Default.ShallowCopy();
+ Configuration cfg = Configuration.Default.Clone();
var metaData = new ImageMetaData();
var array = new Rgba32[25];
diff --git a/tests/ImageSharp.Tests/Image/ImageTests.cs b/tests/ImageSharp.Tests/Image/ImageTests.cs
index ed142ed97..f3c04d5e1 100644
--- a/tests/ImageSharp.Tests/Image/ImageTests.cs
+++ b/tests/ImageSharp.Tests/Image/ImageTests.cs
@@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
public void Configuration_Width_Height()
{
- Configuration configuration = Configuration.Default.ShallowCopy();
+ Configuration configuration = Configuration.Default.Clone();
using (var image = new Image(configuration, 11, 23))
{
@@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
public void Configuration_Width_Height_BackroundColor()
{
- Configuration configuration = Configuration.Default.ShallowCopy();
+ Configuration configuration = Configuration.Default.Clone();
Rgba32 color = Rgba32.Aquamarine;
using (var image = new Image(configuration, 11, 23, color))
diff --git a/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs b/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs
index 0a0ca1efa..8c4903960 100644
--- a/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs
+++ b/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs
@@ -32,5 +32,13 @@ namespace SixLabors.ImageSharp.Tests
Assert.Equal(colorTableLength, cloneGifFrameMetaData.ColorTableLength);
Assert.Equal(disposalMethod, cloneGifFrameMetaData.DisposalMethod);
}
+
+ [Fact]
+ public void CloneIsDeep()
+ {
+ var metaData = new ImageFrameMetaData();
+ ImageFrameMetaData clone = metaData.DeepClone();
+ Assert.False(metaData.GetFormatMetaData(GifFormat.Instance).Equals(clone.GetFormatMetaData(GifFormat.Instance)));
+ }
}
}
diff --git a/tests/ImageSharp.Tests/MetaData/ImageMetaDataTests.cs b/tests/ImageSharp.Tests/MetaData/ImageMetaDataTests.cs
index d681c90ba..b9619cb3f 100644
--- a/tests/ImageSharp.Tests/MetaData/ImageMetaDataTests.cs
+++ b/tests/ImageSharp.Tests/MetaData/ImageMetaDataTests.cs
@@ -1,7 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder;
+using SixLabors.ImageSharp.Formats.Gif;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.MetaData.Profiles.Exif;
using SixLabors.ImageSharp.PixelFormats;
@@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.Tests
metaData.VerticalResolution = 2;
metaData.Properties.Add(imageProperty);
- ImageMetaData clone = metaData.Clone();
+ ImageMetaData clone = metaData.DeepClone();
Assert.Equal(exifProfile.ToByteArray(), clone.ExifProfile.ToByteArray());
Assert.Equal(4, clone.HorizontalResolution);
@@ -37,19 +37,43 @@ namespace SixLabors.ImageSharp.Tests
Assert.Equal(imageProperty, clone.Properties[0]);
}
+ [Fact]
+ public void CloneIsDeep()
+ {
+ var metaData = new ImageMetaData();
+
+ var exifProfile = new ExifProfile();
+ var imageProperty = new ImageProperty("name", "value");
+
+ metaData.ExifProfile = exifProfile;
+ metaData.HorizontalResolution = 4;
+ metaData.VerticalResolution = 2;
+ metaData.Properties.Add(imageProperty);
+
+ ImageMetaData clone = metaData.DeepClone();
+ clone.HorizontalResolution = 2;
+ clone.VerticalResolution = 4;
+
+ Assert.False(metaData.ExifProfile.Equals(clone.ExifProfile));
+ Assert.False(metaData.HorizontalResolution.Equals(clone.HorizontalResolution));
+ Assert.False(metaData.VerticalResolution.Equals(clone.VerticalResolution));
+ Assert.False(metaData.Properties.Equals(clone.Properties));
+ Assert.False(metaData.GetFormatMetaData(GifFormat.Instance).Equals(clone.GetFormatMetaData(GifFormat.Instance)));
+ }
+
[Fact]
public void HorizontalResolution()
{
var metaData = new ImageMetaData();
Assert.Equal(96, metaData.HorizontalResolution);
- metaData.HorizontalResolution=0;
+ metaData.HorizontalResolution = 0;
Assert.Equal(96, metaData.HorizontalResolution);
- metaData.HorizontalResolution=-1;
+ metaData.HorizontalResolution = -1;
Assert.Equal(96, metaData.HorizontalResolution);
- metaData.HorizontalResolution=1;
+ metaData.HorizontalResolution = 1;
Assert.Equal(1, metaData.HorizontalResolution);
}
diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs
index 3deb382ea..c10ffb6c8 100644
--- a/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs
+++ b/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs
@@ -67,16 +67,16 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
public void ConstructorCopy()
{
- Assert.Throws(() => { new ExifProfile((ExifProfile)null); });
+ Assert.Throws(() => ((ExifProfile)null).DeepClone());
ExifProfile profile = GetExifProfile();
- var clone = new ExifProfile(profile);
+ ExifProfile clone = profile.DeepClone();
TestProfile(clone);
profile.SetValue(ExifTag.ColorSpace, (ushort)2);
- clone = new ExifProfile(profile);
+ clone = profile.DeepClone();
TestProfile(clone);
}
@@ -234,10 +234,12 @@ namespace SixLabors.ImageSharp.Tests
exifProfile.SetValue(ExifTag.XResolution, new Rational(200));
exifProfile.SetValue(ExifTag.YResolution, new Rational(300));
- var metaData = new ImageMetaData();
- metaData.ExifProfile = exifProfile;
- metaData.HorizontalResolution = 200;
- metaData.VerticalResolution = 300;
+ var metaData = new ImageMetaData
+ {
+ ExifProfile = exifProfile,
+ HorizontalResolution = 200,
+ VerticalResolution = 300
+ };
metaData.HorizontalResolution = 100;
@@ -355,11 +357,11 @@ namespace SixLabors.ImageSharp.Tests
// act
Image reloadedImage = WriteAndRead(image, imageFormat);
-
+
// assert
ExifProfile actual = reloadedImage.MetaData.ExifProfile;
Assert.NotNull(actual);
- foreach(KeyValuePair expectedProfileValue in TestProfileValues)
+ foreach (KeyValuePair expectedProfileValue in TestProfileValues)
{
ExifValue actualProfileValue = actual.GetValue(expectedProfileValue.Key);
Assert.NotNull(actualProfileValue);
@@ -371,7 +373,7 @@ namespace SixLabors.ImageSharp.Tests
public void ProfileToByteArray()
{
// arrange
- byte[] exifBytesWithExifCode = ProfileResolver.ExifMarker.Concat(ExifConstants.LittleEndianByteOrderMarker).ToArray();
+ byte[] exifBytesWithExifCode = ProfileResolver.ExifMarker.Concat(ExifConstants.LittleEndianByteOrderMarker).ToArray();
byte[] exifBytesWithoutExifCode = ExifConstants.LittleEndianByteOrderMarker;
ExifProfile expectedProfile = CreateExifProfile();
var expectedProfileTags = expectedProfile.Values.Select(x => x.Tag).ToList();
@@ -384,7 +386,7 @@ namespace SixLabors.ImageSharp.Tests
Assert.NotNull(actualBytes);
Assert.NotEmpty(actualBytes);
Assert.Equal(exifBytesWithoutExifCode, actualBytes.Take(exifBytesWithoutExifCode.Length).ToArray());
- foreach(ExifTag expectedProfileTag in expectedProfileTags)
+ foreach (ExifTag expectedProfileTag in expectedProfileTags)
{
ExifValue actualProfileValue = actualProfile.GetValue(expectedProfileTag);
ExifValue expectedProfileValue = expectedProfile.GetValue(expectedProfileTag);
@@ -396,7 +398,7 @@ namespace SixLabors.ImageSharp.Tests
{
var profile = new ExifProfile();
- foreach(KeyValuePair exifProfileValue in TestProfileValues)
+ foreach (KeyValuePair exifProfileValue in TestProfileValues)
{
profile.SetValue(exifProfileValue.Key, exifProfileValue.Value);
}
@@ -416,7 +418,7 @@ namespace SixLabors.ImageSharp.Tests
private static Image WriteAndRead(Image image, TestImageWriteFormat imageFormat)
{
- switch(imageFormat)
+ switch (imageFormat)
{
case TestImageWriteFormat.Jpeg:
return WriteAndReadJpeg(image);
diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs
index ab0cc42f9..30ac0856c 100644
--- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs
@@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Tests
public virtual string SourceFileOrDescription => "";
- public Configuration Configuration { get; set; } = Configuration.Default.ShallowCopy();
+ public Configuration Configuration { get; set; } = Configuration.Default.Clone();
///
/// Utility instance to provide informations about the test image & manage input/output