Browse Source

Add Clone overloads for new configuration.

af/merge-core
James Jackson-South 7 years ago
parent
commit
6e47624413
  1. 2
      src/ImageSharp/Configuration.cs
  2. 50
      src/ImageSharp/ImageFrame{TPixel}.cs
  3. 88
      src/ImageSharp/Image{TPixel}.cs
  4. 2
      tests/ImageSharp.Tests/ConfigurationTests.cs
  5. 2
      tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs
  6. 4
      tests/ImageSharp.Tests/Image/ImageTests.cs
  7. 2
      tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs

2
src/ImageSharp/Configuration.cs

@ -125,7 +125,7 @@ namespace SixLabors.ImageSharp
/// Creates a shallow copy of the <see cref="Configuration"/> /// Creates a shallow copy of the <see cref="Configuration"/>
/// </summary> /// </summary>
/// <returns>A new configuration instance</returns> /// <returns>A new configuration instance</returns>
public Configuration ShallowCopy() public Configuration Clone()
{ {
return new Configuration return new Configuration
{ {

50
src/ImageSharp/ImageFrame{TPixel}.cs

@ -95,6 +95,10 @@ namespace SixLabors.ImageSharp
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ImageFrame{TPixel}" /> class wrapping an existing buffer. /// Initializes a new instance of the <see cref="ImageFrame{TPixel}" /> class wrapping an existing buffer.
/// </summary> /// </summary>
/// <param name="configuration">The configuration providing initialization code which allows extending the library.</param>
/// <param name="width">The width of the image in pixels.</param>
/// <param name="height">The height of the image in pixels.</param>
/// <param name="memorySource">The memory source.</param>
internal ImageFrame(Configuration configuration, int width, int height, MemorySource<TPixel> memorySource) internal ImageFrame(Configuration configuration, int width, int height, MemorySource<TPixel> memorySource)
: this(configuration, width, height, memorySource, new ImageFrameMetaData()) : this(configuration, width, height, memorySource, new ImageFrameMetaData())
{ {
@ -103,12 +107,12 @@ namespace SixLabors.ImageSharp
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ImageFrame{TPixel}" /> class wrapping an existing buffer. /// Initializes a new instance of the <see cref="ImageFrame{TPixel}" /> class wrapping an existing buffer.
/// </summary> /// </summary>
internal ImageFrame( /// <param name="configuration">The configuration providing initialization code which allows extending the library.</param>
Configuration configuration, /// <param name="width">The width of the image in pixels.</param>
int width, /// <param name="height">The height of the image in pixels.</param>
int height, /// <param name="memorySource">The memory source.</param>
MemorySource<TPixel> memorySource, /// <param name="metaData">The meta data.</param>
ImageFrameMetaData metaData) internal ImageFrame(Configuration configuration, int width, int height, MemorySource<TPixel> memorySource, ImageFrameMetaData metaData)
{ {
Guard.NotNull(configuration, nameof(configuration)); Guard.NotNull(configuration, nameof(configuration));
Guard.MustBeGreaterThan(width, 0, nameof(width)); Guard.MustBeGreaterThan(width, 0, nameof(width));
@ -247,25 +251,47 @@ namespace SixLabors.ImageSharp
/// <inheritdoc/> /// <inheritdoc/>
public override string ToString() => $"ImageFrame<{typeof(TPixel).Name}>: {this.Width}x{this.Height}"; public override string ToString() => $"ImageFrame<{typeof(TPixel).Name}>: {this.Width}x{this.Height}";
/// <summary>
/// Clones the current instance.
/// </summary>
/// <returns>The <see cref="ImageFrame{TPixel}"/></returns>
internal ImageFrame<TPixel> Clone() => this.Clone(this.configuration);
/// <summary>
/// Clones the current instance.
/// </summary>
/// <param name="configuration">The configuration providing initialization code which allows extending the library.</param>
/// <returns>The <see cref="ImageFrame{TPixel}"/></returns>
internal ImageFrame<TPixel> Clone(Configuration configuration) => new ImageFrame<TPixel>(configuration, this);
/// <summary> /// <summary>
/// Returns a copy of the image frame in the given pixel format. /// Returns a copy of the image frame in the given pixel format.
/// </summary> /// </summary>
/// <typeparam name="TPixel2">The pixel format.</typeparam> /// <typeparam name="TPixel2">The pixel format.</typeparam>
/// <returns>The <see cref="ImageFrame{TPixel2}"/></returns> /// <returns>The <see cref="ImageFrame{TPixel2}"/></returns>
internal ImageFrame<TPixel2> CloneAs<TPixel2>() internal ImageFrame<TPixel2> CloneAs<TPixel2>()
where TPixel2 : struct, IPixel<TPixel2> => this.CloneAs<TPixel2>(this.configuration);
/// <summary>
/// Returns a copy of the image frame in the given pixel format.
/// </summary>
/// <typeparam name="TPixel2">The pixel format.</typeparam>
/// <param name="configuration">The configuration providing initialization code which allows extending the library.</param>
/// <returns>The <see cref="ImageFrame{TPixel2}"/></returns>
internal ImageFrame<TPixel2> CloneAs<TPixel2>(Configuration configuration)
where TPixel2 : struct, IPixel<TPixel2> where TPixel2 : struct, IPixel<TPixel2>
{ {
if (typeof(TPixel2) == typeof(TPixel)) if (typeof(TPixel2) == typeof(TPixel))
{ {
return this.Clone() as ImageFrame<TPixel2>; return this.Clone(configuration) as ImageFrame<TPixel2>;
} }
var target = new ImageFrame<TPixel2>(this.configuration, this.Width, this.Height, this.MetaData.Clone()); var target = new ImageFrame<TPixel2>(configuration, this.Width, this.Height, this.MetaData.Clone());
ParallelFor.WithTemporaryBuffer( ParallelFor.WithTemporaryBuffer(
0, 0,
this.Height, this.Height,
this.configuration, configuration,
this.Width, this.Width,
(int y, IMemoryOwner<Vector4> tempRowBuffer) => (int y, IMemoryOwner<Vector4> tempRowBuffer) =>
{ {
@ -298,12 +324,6 @@ namespace SixLabors.ImageSharp
}); });
} }
/// <summary>
/// Clones the current instance.
/// </summary>
/// <returns>The <see cref="ImageFrame{TPixel}"/></returns>
internal ImageFrame<TPixel> Clone() => new ImageFrame<TPixel>(this.configuration, this);
/// <inheritdoc/> /// <inheritdoc/>
void IDisposable.Dispose() => this.Dispose(); void IDisposable.Dispose() => this.Dispose();
} }

88
src/ImageSharp/Image{TPixel}.cs

@ -11,7 +11,6 @@ using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.MetaData; using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
namespace SixLabors.ImageSharp namespace SixLabors.ImageSharp
{ {
@ -23,15 +22,12 @@ namespace SixLabors.ImageSharp
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
private readonly Configuration configuration; private readonly Configuration configuration;
private readonly ImageFrameCollection<TPixel> frames;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Image{TPixel}"/> class /// Initializes a new instance of the <see cref="Image{TPixel}"/> class
/// with the height and the width of the image. /// with the height and the width of the image.
/// </summary> /// </summary>
/// <param name="configuration"> /// <param name="configuration">The configuration providing initialization code which allows extending the library.</param>
/// The configuration providing initialization code which allows extending the library.
/// </param>
/// <param name="width">The width of the image in pixels.</param> /// <param name="width">The width of the image in pixels.</param>
/// <param name="height">The height of the image in pixels.</param> /// <param name="height">The height of the image in pixels.</param>
public Image(Configuration configuration, int width, int height) public Image(Configuration configuration, int width, int height)
@ -43,9 +39,7 @@ namespace SixLabors.ImageSharp
/// Initializes a new instance of the <see cref="Image{TPixel}"/> class /// Initializes a new instance of the <see cref="Image{TPixel}"/> class
/// with the height and the width of the image. /// with the height and the width of the image.
/// </summary> /// </summary>
/// <param name="configuration"> /// <param name="configuration">The configuration providing initialization code which allows extending the library.</param>
/// The configuration providing initialization code which allows extending the library.
/// </param>
/// <param name="width">The width of the image in pixels.</param> /// <param name="width">The width of the image in pixels.</param>
/// <param name="height">The height of the image in pixels.</param> /// <param name="height">The height of the image in pixels.</param>
/// <param name="backgroundColor">The color to initialize the pixels with.</param> /// <param name="backgroundColor">The color to initialize the pixels with.</param>
@ -69,9 +63,7 @@ namespace SixLabors.ImageSharp
/// Initializes a new instance of the <see cref="Image{TPixel}"/> class /// Initializes a new instance of the <see cref="Image{TPixel}"/> class
/// with the height and the width of the image. /// with the height and the width of the image.
/// </summary> /// </summary>
/// <param name="configuration"> /// <param name="configuration">The configuration providing initialization code which allows extending the library.</param>
/// The configuration providing initialization code which allows extending the library.
/// </param>
/// <param name="width">The width of the image in pixels.</param> /// <param name="width">The width of the image in pixels.</param>
/// <param name="height">The height of the image in pixels.</param> /// <param name="height">The height of the image in pixels.</param>
/// <param name="metadata">The images metadata.</param> /// <param name="metadata">The images metadata.</param>
@ -80,37 +72,41 @@ namespace SixLabors.ImageSharp
this.configuration = configuration ?? Configuration.Default; this.configuration = configuration ?? Configuration.Default;
this.PixelType = new PixelTypeInfo(Unsafe.SizeOf<TPixel>() * 8); this.PixelType = new PixelTypeInfo(Unsafe.SizeOf<TPixel>() * 8);
this.MetaData = metadata ?? new ImageMetaData(); this.MetaData = metadata ?? new ImageMetaData();
this.frames = new ImageFrameCollection<TPixel>(this, width, height, default(TPixel)); this.Frames = new ImageFrameCollection<TPixel>(this, width, height, default(TPixel));
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Image{TPixel}"/> class /// Initializes a new instance of the <see cref="Image{TPixel}"/> class
/// wrapping an external <see cref="MemorySource{T}"/> /// wrapping an external <see cref="MemorySource{T}"/>
/// </summary> /// </summary>
/// <param name="configuration">The configuration providing initialization code which allows extending the library.</param>
/// <param name="memorySource">The memory source.</param>
/// <param name="width">The width of the image in pixels.</param>
/// <param name="height">The height of the image in pixels.</param>
/// <param name="metadata">The images metadata.</param>
internal Image(Configuration configuration, MemorySource<TPixel> memorySource, int width, int height, ImageMetaData metadata) internal Image(Configuration configuration, MemorySource<TPixel> memorySource, int width, int height, ImageMetaData metadata)
{ {
this.configuration = configuration; this.configuration = configuration;
this.PixelType = new PixelTypeInfo(Unsafe.SizeOf<TPixel>() * 8); this.PixelType = new PixelTypeInfo(Unsafe.SizeOf<TPixel>() * 8);
this.MetaData = metadata; this.MetaData = metadata;
this.frames = new ImageFrameCollection<TPixel>(this, width, height, memorySource); this.Frames = new ImageFrameCollection<TPixel>(this, width, height, memorySource);
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Image{TPixel}"/> class /// Initializes a new instance of the <see cref="Image{TPixel}"/> class
/// with the height and the width of the image. /// with the height and the width of the image.
/// </summary> /// </summary>
/// <param name="configuration"> /// <param name="configuration">The configuration providing initialization code which allows extending the library.</param>
/// The configuration providing initialization code which allows extending the library.
/// </param>
/// <param name="width">The width of the image in pixels.</param> /// <param name="width">The width of the image in pixels.</param>
/// <param name="height">The height of the image in pixels.</param> /// <param name="height">The height of the image in pixels.</param>
/// <param name="backgroundColor">The color to initialize the pixels with.</param> /// <param name="backgroundColor">The color to initialize the pixels with.</param>
/// <param name="metadata">The images metadata.</param> /// <param name="metadata">The images metadata.</param>
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.configuration = configuration ?? Configuration.Default;
this.PixelType = new PixelTypeInfo(Unsafe.SizeOf<TPixel>() * 8); this.PixelType = new PixelTypeInfo(Unsafe.SizeOf<TPixel>() * 8);
this.MetaData = metadata ?? new ImageMetaData(); this.MetaData = metadata ?? new ImageMetaData();
this.frames = new ImageFrameCollection<TPixel>(this, width, height, backgroundColor); this.Frames = new ImageFrameCollection<TPixel>(this, width, height, backgroundColor);
} }
/// <summary> /// <summary>
@ -126,7 +122,7 @@ namespace SixLabors.ImageSharp
this.PixelType = new PixelTypeInfo(Unsafe.SizeOf<TPixel>() * 8); this.PixelType = new PixelTypeInfo(Unsafe.SizeOf<TPixel>() * 8);
this.MetaData = metadata ?? new ImageMetaData(); this.MetaData = metadata ?? new ImageMetaData();
this.frames = new ImageFrameCollection<TPixel>(this, frames); this.Frames = new ImageFrameCollection<TPixel>(this, frames);
} }
/// <summary> /// <summary>
@ -138,10 +134,10 @@ namespace SixLabors.ImageSharp
public PixelTypeInfo PixelType { get; } public PixelTypeInfo PixelType { get; }
/// <inheritdoc/> /// <inheritdoc/>
public int Width => this.frames.RootFrame.Width; public int Width => this.Frames.RootFrame.Width;
/// <inheritdoc/> /// <inheritdoc/>
public int Height => this.frames.RootFrame.Height; public int Height => this.Frames.RootFrame.Height;
/// <inheritdoc/> /// <inheritdoc/>
public ImageMetaData MetaData { get; } public ImageMetaData MetaData { get; }
@ -149,12 +145,12 @@ namespace SixLabors.ImageSharp
/// <summary> /// <summary>
/// Gets the frames. /// Gets the frames.
/// </summary> /// </summary>
public ImageFrameCollection<TPixel> Frames => this.frames; public ImageFrameCollection<TPixel> Frames { get; }
/// <summary> /// <summary>
/// Gets the root frame. /// Gets the root frame.
/// </summary> /// </summary>
private IPixelSource<TPixel> PixelSource => this.frames?.RootFrame ?? throw new ObjectDisposedException(nameof(Image<TPixel>)); private IPixelSource<TPixel> PixelSource => this.Frames?.RootFrame ?? throw new ObjectDisposedException(nameof(Image<TPixel>));
/// <summary> /// <summary>
/// Gets or sets the pixel at the specified position. /// Gets or sets the pixel at the specified position.
@ -187,16 +183,17 @@ namespace SixLabors.ImageSharp
/// Clones the current image /// Clones the current image
/// </summary> /// </summary>
/// <returns>Returns a new image with all the same metadata as the original.</returns> /// <returns>Returns a new image with all the same metadata as the original.</returns>
public Image<TPixel> Clone() public Image<TPixel> Clone() => this.Clone(this.configuration);
{
IEnumerable<ImageFrame<TPixel>> clonedFrames = this.frames.Select(x => x.Clone());
return new Image<TPixel>(this.configuration, this.MetaData.Clone(), clonedFrames);
}
/// <inheritdoc/> /// <summary>
public override string ToString() /// Clones the current image with the given configueation.
/// </summary>
/// <param name="configuration">The configuration providing initialization code which allows extending the library.</param>
/// <returns>Returns a new <see cref="Image{TPixel}"/> with all the same pixel data as the original.</returns>
public Image<TPixel> Clone(Configuration configuration)
{ {
return $"Image<{typeof(TPixel).Name}>: {this.Width}x{this.Height}"; IEnumerable<ImageFrame<TPixel>> clonedFrames = this.Frames.Select(x => x.Clone(configuration));
return new Image<TPixel>(configuration, this.MetaData.Clone(), clonedFrames);
} }
/// <summary> /// <summary>
@ -205,22 +202,27 @@ namespace SixLabors.ImageSharp
/// <typeparam name="TPixel2">The pixel format.</typeparam> /// <typeparam name="TPixel2">The pixel format.</typeparam>
/// <returns>The <see cref="Image{TPixel2}"/></returns> /// <returns>The <see cref="Image{TPixel2}"/></returns>
public Image<TPixel2> CloneAs<TPixel2>() public Image<TPixel2> CloneAs<TPixel2>()
where TPixel2 : struct, IPixel<TPixel2> where TPixel2 : struct, IPixel<TPixel2> => this.CloneAs<TPixel2>(this.configuration);
{
IEnumerable<ImageFrame<TPixel2>> clonedFrames = this.frames.Select(x => x.CloneAs<TPixel2>());
var target = new Image<TPixel2>(this.configuration, this.MetaData.Clone(), clonedFrames);
return target;
}
/// <summary> /// <summary>
/// Releases managed resources. /// Returns a copy of the image in the given pixel format.
/// </summary> /// </summary>
public void Dispose() /// <typeparam name="TPixel2">The pixel format.</typeparam>
/// <param name="configuration">The configuration providing initialization code which allows extending the library.</param>
/// <returns>The <see cref="Image{TPixel2}"/></returns>
public Image<TPixel2> CloneAs<TPixel2>(Configuration configuration)
where TPixel2 : struct, IPixel<TPixel2>
{ {
this.frames.Dispose(); IEnumerable<ImageFrame<TPixel2>> clonedFrames = this.Frames.Select(x => x.CloneAs<TPixel2>(configuration));
return new Image<TPixel2>(configuration, this.MetaData.Clone(), clonedFrames);
} }
/// <inheritdoc/>
public void Dispose() => this.Frames.Dispose();
/// <inheritdoc/>
public override string ToString() => $"Image<{typeof(TPixel).Name}>: {this.Width}x{this.Height}";
/// <summary> /// <summary>
/// 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. /// 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.
/// </summary> /// </summary>
@ -229,9 +231,9 @@ namespace SixLabors.ImageSharp
{ {
Guard.NotNull(pixelSource, nameof(pixelSource)); 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]);
} }
} }
} }

2
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, // 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. // 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(); this.ConfigurationEmpty = new Configuration();
} }

2
tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs

@ -84,7 +84,7 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void WrapMemory_CreatedImageIsCorrect() public void WrapMemory_CreatedImageIsCorrect()
{ {
Configuration cfg = Configuration.Default.ShallowCopy(); Configuration cfg = Configuration.Default.Clone();
var metaData = new ImageMetaData(); var metaData = new ImageMetaData();
var array = new Rgba32[25]; var array = new Rgba32[25];

4
tests/ImageSharp.Tests/Image/ImageTests.cs

@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void Configuration_Width_Height() public void Configuration_Width_Height()
{ {
Configuration configuration = Configuration.Default.ShallowCopy(); Configuration configuration = Configuration.Default.Clone();
using (var image = new Image<Rgba32>(configuration, 11, 23)) using (var image = new Image<Rgba32>(configuration, 11, 23))
{ {
@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.Tests
[Fact] [Fact]
public void Configuration_Width_Height_BackroundColor() public void Configuration_Width_Height_BackroundColor()
{ {
Configuration configuration = Configuration.Default.ShallowCopy(); Configuration configuration = Configuration.Default.Clone();
Rgba32 color = Rgba32.Aquamarine; Rgba32 color = Rgba32.Aquamarine;
using (var image = new Image<Rgba32>(configuration, 11, 23, color)) using (var image = new Image<Rgba32>(configuration, 11, 23, color))

2
tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs

@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Tests
public virtual string SourceFileOrDescription => ""; public virtual string SourceFileOrDescription => "";
public Configuration Configuration { get; set; } = Configuration.Default.ShallowCopy(); public Configuration Configuration { get; set; } = Configuration.Default.Clone();
/// <summary> /// <summary>
/// Utility instance to provide informations about the test image & manage input/output /// Utility instance to provide informations about the test image & manage input/output

Loading…
Cancel
Save