Skip to content

Commit

Permalink
Added CloneArea to MagickImage that will replace the Clone overload w…
Browse files Browse the repository at this point in the history
…ith a MagickGeometry.
  • Loading branch information
dlemstra committed Sep 19, 2024
1 parent 32996b4 commit c591004
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 20 deletions.
29 changes: 29 additions & 0 deletions src/Magick.NET.Core/IMagickImage{TQuantumType}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public partial interface IMagickImage<TQuantumType> : IMagickImage, IComparable<
/// <param name="geometry">The area to clone.</param>
/// <returns>A clone of the current image.</returns>
/// <exception cref="MagickException">Thrown when an error is raised by ImageMagick.</exception>
[Obsolete($"This property will be removed in the next major release, use {nameof(CloneArea)} instead.")]
IMagickImage<TQuantumType> Clone(IMagickGeometry geometry);

/// <summary>
Expand All @@ -57,6 +58,7 @@ public partial interface IMagickImage<TQuantumType> : IMagickImage, IComparable<
/// <param name="width">The width of the area to clone.</param>
/// <param name="height">The height of the area to clone.</param>
/// <returns>A clone of the current image.</returns>
[Obsolete($"This property will be removed in the next major release, use {nameof(CloneArea)} instead.")]
IMagickImage<TQuantumType> Clone(uint width, uint height);

/// <summary>
Expand All @@ -67,8 +69,35 @@ public partial interface IMagickImage<TQuantumType> : IMagickImage, IComparable<
/// <param name="width">The width of the area to clone.</param>
/// <param name="height">The height of the area to clone.</param>
/// <returns>A clone of the current image.</returns>
[Obsolete($"This property will be removed in the next major release, use {nameof(CloneArea)} instead.")]
IMagickImage<TQuantumType> Clone(int x, int y, uint width, uint height);

/// <summary>
/// Creates a clone of the current image with the specified geometry.
/// </summary>
/// <param name="geometry">The area to clone.</param>
/// <returns>A clone of the current image.</returns>
/// <exception cref="MagickException">Thrown when an error is raised by ImageMagick.</exception>
IMagickImage<TQuantumType> CloneArea(IMagickGeometry geometry);

/// <summary>
/// Creates a clone of the current image.
/// </summary>
/// <param name="width">The width of the area to clone.</param>
/// <param name="height">The height of the area to clone.</param>
/// <returns>A clone of the current image.</returns>
IMagickImage<TQuantumType> CloneArea(uint width, uint height);

/// <summary>
/// Creates a clone of the current image.
/// </summary>
/// <param name="x">The X offset from origin.</param>
/// <param name="y">The Y offset from origin.</param>
/// <param name="width">The width of the area to clone.</param>
/// <param name="height">The height of the area to clone.</param>
/// <returns>A clone of the current image.</returns>
IMagickImage<TQuantumType> CloneArea(int x, int y, uint width, uint height);

/// <summary>
/// Sets the alpha channel to the specified color.
/// </summary>
Expand Down
40 changes: 36 additions & 4 deletions src/Magick.NET/MagickImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1519,7 +1519,39 @@ public IMagickImage<QuantumType> Clone()
/// <param name="geometry">The area to clone.</param>
/// <returns>A clone of the current image.</returns>
/// <exception cref="MagickException">Thrown when an error is raised by ImageMagick.</exception>
[Obsolete($"This property will be removed in the next major release, use {nameof(CloneArea)} instead.")]
public IMagickImage<QuantumType> Clone(IMagickGeometry geometry)
=> CloneArea(geometry);

/// <summary>
/// Creates a clone of the current image.
/// </summary>
/// <param name="width">The width of the area to clone.</param>
/// <param name="height">The height of the area to clone.</param>
/// <returns>A clone of the current image.</returns>
[Obsolete($"This property will be removed in the next major release, use {nameof(CloneArea)} instead.")]
public IMagickImage<QuantumType> Clone(uint width, uint height)
=> CloneArea(new MagickGeometry(width, height));

/// <summary>
/// Creates a clone of the current image.
/// </summary>
/// <param name="x">The X offset from origin.</param>
/// <param name="y">The Y offset from origin.</param>
/// <param name="width">The width of the area to clone.</param>
/// <param name="height">The height of the area to clone.</param>
/// <returns>A clone of the current image.</returns>
[Obsolete($"This property will be removed in the next major release, use {nameof(CloneArea)} instead.")]
public IMagickImage<QuantumType> Clone(int x, int y, uint width, uint height)
=> CloneArea(new MagickGeometry(x, y, width, height));

/// <summary>
/// Creates a clone of the current image with the specified geometry.
/// </summary>
/// <param name="geometry">The area to clone.</param>
/// <returns>A clone of the current image.</returns>
/// <exception cref="MagickException">Thrown when an error is raised by ImageMagick.</exception>
public IMagickImage<QuantumType> CloneArea(IMagickGeometry geometry)
{
Throw.IfNull(nameof(geometry), geometry);

Expand All @@ -1537,8 +1569,8 @@ public IMagickImage<QuantumType> Clone(IMagickGeometry geometry)
/// <param name="width">The width of the area to clone.</param>
/// <param name="height">The height of the area to clone.</param>
/// <returns>A clone of the current image.</returns>
public IMagickImage<QuantumType> Clone(uint width, uint height)
=> Clone(new MagickGeometry(width, height));
public IMagickImage<QuantumType> CloneArea(uint width, uint height)
=> CloneArea(new MagickGeometry(width, height));

/// <summary>
/// Creates a clone of the current image.
Expand All @@ -1548,8 +1580,8 @@ public IMagickImage<QuantumType> Clone(uint width, uint height)
/// <param name="width">The width of the area to clone.</param>
/// <param name="height">The height of the area to clone.</param>
/// <returns>A clone of the current image.</returns>
public IMagickImage<QuantumType> Clone(int x, int y, uint width, uint height)
=> Clone(new MagickGeometry(x, y, width, height));
public IMagickImage<QuantumType> CloneArea(int x, int y, uint width, uint height)
=> CloneArea(new MagickGeometry(x, y, width, height));

/// <summary>
/// Apply a color lookup table (CLUT) to the image.
Expand Down
74 changes: 74 additions & 0 deletions tests/Magick.NET.Tests/MagickImageTests/TheCloneAreaMethod.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright Dirk Lemstra https://github.com/dlemstra/Magick.NET.
// Licensed under the Apache License, Version 2.0.

using ImageMagick;
using Xunit;

namespace Magick.NET.Tests;

public partial class MagickImageTests
{
public class TheCloneAreaMethod
{
public class WithGeometry
{
[Fact]
public void ShouldCloneTheSpecifiedGeometry()
{
using var icon = new MagickImage(Files.MagickNETIconPNG);
using var area = icon.Clone();
area.Crop(64, 64, Gravity.Southeast);
area.ResetPage();
area.Crop(64, 32, Gravity.North);

using var part = icon.CloneArea(new MagickGeometry(64, 64, 64, 32));

Assert.Equal(area.Width, part.Width);
Assert.Equal(area.Height, part.Height);

Assert.Equal(0.0, area.Compare(part, ErrorMetric.RootMeanSquared));
}
}

public class WithWidthAndHeight
{
[Fact]
public void ShouldClonePartOfTheImageWhenWidthAndHeightAreSpecified()
{
using var icon = new MagickImage(Files.MagickNETIconPNG);
using var area = icon.Clone();
area.Crop(32, 64, Gravity.Northwest);

Assert.Equal(32U, area.Width);
Assert.Equal(64U, area.Height);

using var part = icon.CloneArea(32, 64);

Assert.Equal(area.Width, part.Width);
Assert.Equal(area.Height, part.Height);
Assert.Equal(0.0, area.Compare(part, ErrorMetric.RootMeanSquared));
Assert.Equal(8192, part.ToByteArray(MagickFormat.Rgba).Length);
}
}

public class WithWidthAndHeightAndOffset
{
[Fact]
public void ShouldCloneUsingTheSpecifiedOffset()
{
using var icon = new MagickImage(Files.MagickNETIconPNG);
using var area = icon.Clone();
area.Crop(64, 64, Gravity.Southeast);
area.ResetPage();
area.Crop(64, 32, Gravity.North);

using var part = icon.CloneArea(64, 64, 64, 32);

Assert.Equal(area.Width, part.Width);
Assert.Equal(area.Height, part.Height);

Assert.Equal(0.0, area.Compare(part, ErrorMetric.RootMeanSquared));
}
}
}
}
32 changes: 16 additions & 16 deletions tests/Magick.NET.Tests/MagickImageTests/TheCloneMethod.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright Dirk Lemstra https://github.com/dlemstra/Magick.NET.
// Licensed under the Apache License, Version 2.0.

using System;
using ImageMagick;
using Xunit;

Expand All @@ -10,31 +11,28 @@ public partial class MagickImageTests
{
public class TheCloneMethod
{
public class WithoutArguments
[Fact]
public void ShouldThrowExceptionWhenNoImageIsRead()
{
[Fact]
public void ShouldThrowExceptionWhenNoImageIsRead()
{
using var image = new MagickImage();
using var image = new MagickImage();

Assert.Throws<MagickCorruptImageErrorException>(() => image.Clone());
}
Assert.Throws<MagickCorruptImageErrorException>(() => image.Clone());
}

[Fact]
public void ShouldCloneTheImage()
{
using var image = new MagickImage(Files.Builtin.Logo);
[Fact]
public void ShouldCloneTheImage()
{
using var image = new MagickImage(Files.Builtin.Logo);

var clone = image.Clone();
var clone = image.Clone();

Assert.Equal(image, clone);
Assert.False(ReferenceEquals(image, clone));
}
Assert.Equal(image, clone);
Assert.False(ReferenceEquals(image, clone));
}

[Obsolete]
public class WithWidthAndHeight
{
[Fact]
public void ShouldClonePartOfTheImageWhenWidthAndHeightAreSpecified()
{
using var icon = new MagickImage(Files.MagickNETIconPNG);
Expand All @@ -53,6 +51,7 @@ public void ShouldClonePartOfTheImageWhenWidthAndHeightAreSpecified()
}
}

[Obsolete]
public class WithWidthAndHeightAndOffset
{
[Fact]
Expand All @@ -73,6 +72,7 @@ public void ShouldCloneUsingTheSpecifiedOffset()
}
}

[Obsolete]
public class WithGeometry
{
[Fact]
Expand Down

0 comments on commit c591004

Please sign in to comment.