Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: make Percentage only positive #1572

Merged
merged 2 commits into from
Mar 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 24 additions & 8 deletions src/Magick.NET.Core/Types/Percentage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,36 @@ namespace ImageMagick;
/// <summary>
/// Initializes a new instance of the <see cref="Percentage"/> struct.
/// </summary>
/// <param name="value">The value (0% = 0.0, 100% = 100.0).</param>
/// <param name="value">The value (0% = 0.0, 100% = 100.0, 142.42% = 142.42).</param>
public Percentage(double value)
=> _value = value;
{
Throw.IfNegative(nameof(value), value);
dlemstra marked this conversation as resolved.
Show resolved Hide resolved

_value = value;
}

/// <summary>
/// Initializes a new instance of the <see cref="Percentage"/> struct.
/// </summary>
/// <param name="value">The value (0% = 0, 100% = 100).</param>
/// <param name="value">The value (0% = 0, 100% = 100, 142% = 142).</param>
public Percentage(int value)
=> _value = value;
{
Throw.IfNegative(nameof(value), value);

_value = value;
}

/// <summary>
/// Converts the specified double to an instance of this type.
/// </summary>
/// <param name="value">The value (0% = 0, 100% = 100).</param>
/// <param name="value">The value (0% = 0.0, 100% = 100.0, 142.42% = 142.42).</param>
public static explicit operator Percentage(double value)
=> new Percentage(value);

/// <summary>
/// Converts the specified int to an instance of this type.
/// </summary>
/// <param name="value">The value (0% = 0, 100% = 100).</param>
/// <param name="value">The value (0% = 0, 100% = 100, 142% = 142).</param>
public static explicit operator Percentage(int value)
=> new Percentage(value);

Expand Down Expand Up @@ -170,15 +178,23 @@ public override int GetHashCode()
/// <param name="value">The value to use.</param>
/// <returns>The new value.</returns>
public double Multiply(double value)
=> (value * _value) / 100.0;
{
Throw.IfNegative(nameof(value), value);

return (value * _value) / 100.0;
}

/// <summary>
/// Multiplies the value by the specified percentage.
/// </summary>
/// <param name="value">The value to use.</param>
/// <returns>The new value.</returns>
public int Multiply(int value)
=> (int)((value * _value) / 100.0);
{
Throw.IfNegative(nameof(value), value);

return (int)((value * _value) / 100.0);
}

/// <summary>
/// Returns a double that represents the current percentage.
Expand Down
45 changes: 5 additions & 40 deletions src/Magick.NET/MagickImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1358,11 +1358,7 @@ public void BlackThreshold(Percentage threshold)
/// <param name="channels">The channel(s) to make black.</param>
/// <exception cref="MagickException">Thrown when an error is raised by ImageMagick.</exception>
public void BlackThreshold(Percentage threshold, Channels channels)
{
Throw.IfNegative(nameof(threshold), threshold);

_nativeInstance.BlackThreshold(threshold.ToString(), channels);
}
=> _nativeInstance.BlackThreshold(threshold.ToString(), channels);

/// <summary>
/// Simulate a scene at nighttime in the moonlight.
Expand Down Expand Up @@ -1736,11 +1732,7 @@ public void ColorDecisionList(string fileName)
/// <param name="alpha">The alpha percentage.</param>
/// <exception cref="MagickException">Thrown when an error is raised by ImageMagick.</exception>
public void Colorize(IMagickColor<QuantumType> color, Percentage alpha)
{
Throw.IfNegative(nameof(alpha), alpha);

Colorize(color, alpha, alpha, alpha);
}
=> Colorize(color, alpha, alpha, alpha);

/// <summary>
/// Colorize image with the specified color, using specified percent alpha for red, green,
Expand All @@ -1754,9 +1746,6 @@ public void Colorize(IMagickColor<QuantumType> color, Percentage alpha)
public void Colorize(IMagickColor<QuantumType> color, Percentage alphaRed, Percentage alphaGreen, Percentage alphaBlue)
{
Throw.IfNull(nameof(color), color);
Throw.IfNegative(nameof(alphaRed), alphaRed);
Throw.IfNegative(nameof(alphaGreen), alphaGreen);
Throw.IfNegative(nameof(alphaBlue), alphaBlue);

var blend = string.Format(CultureInfo.InvariantCulture, "{0}/{1}/{2}", alphaRed.ToInt32(), alphaGreen.ToInt32(), alphaBlue.ToInt32());

Expand Down Expand Up @@ -2282,9 +2271,6 @@ public void ContrastStretch(Percentage blackPoint, Percentage whitePoint)
/// <exception cref="MagickException">Thrown when an error is raised by ImageMagick.</exception>
public void ContrastStretch(Percentage blackPoint, Percentage whitePoint, Channels channels)
{
Throw.IfNegative(nameof(blackPoint), blackPoint);
Throw.IfNegative(nameof(whitePoint), whitePoint);

var contrast = CalculateContrastStretch(blackPoint, whitePoint);
_nativeInstance.ContrastStretch(contrast.X, contrast.Y, channels);
}
Expand Down Expand Up @@ -2500,7 +2486,6 @@ public double Deskew(Percentage threshold)
public double Deskew(IDeskewSettings settings)
{
Throw.IfNull(nameof(settings), settings);
Throw.IfNegative(nameof(settings), settings.Threshold);

using var temporaryDefines = new TemporaryDefines(this);
temporaryDefines.SetArtifact("deskew:auto-crop", settings.AutoCrop);
Expand Down Expand Up @@ -3849,12 +3834,7 @@ public void LevelColors(IMagickColor<QuantumType> blackColor, IMagickColor<Quant
/// <param name="whitePoint">The white point.</param>
/// <exception cref="MagickException">Thrown when an error is raised by ImageMagick.</exception>
public void LinearStretch(Percentage blackPoint, Percentage whitePoint)
{
Throw.IfNegative(nameof(blackPoint), blackPoint);
Throw.IfNegative(nameof(whitePoint), whitePoint);

_nativeInstance.LinearStretch(PercentageHelper.ToQuantum(blackPoint), PercentageHelper.ToQuantum(whitePoint));
}
=> _nativeInstance.LinearStretch(PercentageHelper.ToQuantum(blackPoint), PercentageHelper.ToQuantum(whitePoint));

/// <summary>
/// Rescales image with seam carving.
Expand Down Expand Up @@ -4125,10 +4105,6 @@ public void Modulate(Percentage brightness, Percentage saturation)
/// <exception cref="MagickException">Thrown when an error is raised by ImageMagick.</exception>
public void Modulate(Percentage brightness, Percentage saturation, Percentage hue)
{
Throw.IfNegative(nameof(brightness), brightness);
Throw.IfNegative(nameof(saturation), saturation);
Throw.IfNegative(nameof(hue), hue);

var modulate = string.Format(CultureInfo.InvariantCulture, "{0}/{1}/{2}", brightness.ToDouble(), saturation.ToDouble(), hue.ToDouble());

_nativeInstance.Modulate(modulate);
Expand Down Expand Up @@ -4698,14 +4674,7 @@ public void RandomThreshold(QuantumType low, QuantumType high, Channels channels
/// <param name="percentageHighBlack">Defines the maximum black threshold value.</param>
/// <exception cref="MagickException">Thrown when an error is raised by ImageMagick.</exception>
public void RangeThreshold(Percentage percentageLowBlack, Percentage percentageLowWhite, Percentage percentageHighWhite, Percentage percentageHighBlack)
{
Throw.IfNegative(nameof(percentageLowBlack), percentageLowBlack);
Throw.IfNegative(nameof(percentageLowWhite), percentageLowWhite);
Throw.IfNegative(nameof(percentageHighWhite), percentageHighWhite);
Throw.IfNegative(nameof(percentageHighBlack), percentageHighBlack);

RangeThreshold(PercentageHelper.ToQuantumType(percentageLowBlack), PercentageHelper.ToQuantumType(percentageLowWhite), PercentageHelper.ToQuantumType(percentageHighWhite), PercentageHelper.ToQuantumType(percentageHighBlack));
}
=> RangeThreshold(PercentageHelper.ToQuantumType(percentageLowBlack), PercentageHelper.ToQuantumType(percentageLowWhite), PercentageHelper.ToQuantumType(percentageHighWhite), PercentageHelper.ToQuantumType(percentageHighBlack));

/// <summary>
/// Applies soft and hard thresholding.
Expand Down Expand Up @@ -6908,11 +6877,7 @@ public void WhiteThreshold(Percentage threshold)
/// <param name="channels">The channel(s) to make black.</param>
/// <exception cref="MagickException">Thrown when an error is raised by ImageMagick.</exception>
public void WhiteThreshold(Percentage threshold, Channels channels)
{
Throw.IfNegative(nameof(threshold), threshold);

_nativeInstance.WhiteThreshold(threshold.ToString(), channels);
}
=> _nativeInstance.WhiteThreshold(threshold.ToString(), channels);

/// <summary>
/// Writes the image to the specified file.
Expand Down
6 changes: 1 addition & 5 deletions src/Magick.NET/ResourceLimits.cs
Original file line number Diff line number Diff line change
Expand Up @@ -204,11 +204,7 @@ ulong IResourceLimits.Width
/// </summary>
/// <param name="percentage">The percentage to use.</param>
public static void LimitMemory(Percentage percentage)
{
Throw.IfOutOfRange(nameof(percentage), percentage);

NativeResourceLimits.LimitMemory((double)percentage / 100.0);
}
=> NativeResourceLimits.LimitMemory((double)percentage / 100.0);

/// <summary>
/// Set the maximum percentage of memory that can be used for image data. This also changes
Expand Down
14 changes: 2 additions & 12 deletions src/Magick.NET/Types/MagickGeometry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,7 @@ public MagickGeometry(int x, int y, int width, int height)
/// <param name="percentageWidth">The percentage of the width.</param>
/// <param name="percentageHeight">The percentage of the height.</param>
public MagickGeometry(Percentage percentageWidth, Percentage percentageHeight)
{
Throw.IfNegative(nameof(percentageWidth), percentageWidth);
Throw.IfNegative(nameof(percentageHeight), percentageHeight);

InitializeFromPercentage(0, 0, (int)percentageWidth, (int)percentageHeight);
}
=> InitializeFromPercentage(0, 0, (int)percentageWidth, (int)percentageHeight);

/// <summary>
/// Initializes a new instance of the <see cref="MagickGeometry"/> class using the specified offsets, width and height.
Expand All @@ -63,12 +58,7 @@ public MagickGeometry(Percentage percentageWidth, Percentage percentageHeight)
/// <param name="percentageWidth">The percentage of the width.</param>
/// <param name="percentageHeight">The percentage of the height.</param>
public MagickGeometry(int x, int y, Percentage percentageWidth, Percentage percentageHeight)
{
Throw.IfNegative(nameof(percentageWidth), percentageWidth);
Throw.IfNegative(nameof(percentageHeight), percentageHeight);

InitializeFromPercentage(x, y, (int)percentageWidth, (int)percentageHeight);
}
=> InitializeFromPercentage(x, y, (int)percentageWidth, (int)percentageHeight);

/// <summary>
/// Initializes a new instance of the <see cref="MagickGeometry"/> class using the specified geometry.
Expand Down
6 changes: 6 additions & 0 deletions src/Shared/Throw.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ public static void IfNegative(string paramName, int value)
throw new ArgumentException("Value should not be negative.", paramName);
}

public static void IfNegative(string paramName, double value)
{
if (value < 0.0)
throw new ArgumentException("Value should not be negative.", paramName);
}

public static void IfNegative(string paramName, Percentage value)
{
if ((double)value < 0.0)
Expand Down
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,6 +11,15 @@ public partial class PercentageTests
{
public class TheConstructor
{
[Fact]
public void ShouldThrowExceptionWhenValueIsNegative()
{
Assert.Throws<ArgumentException>("value", () => new Percentage(-1.0));
Assert.Throws<ArgumentException>("value", () => (Percentage)(-1.0));
Assert.Throws<ArgumentException>("value", () => new Percentage(-1));
Assert.Throws<ArgumentException>("value", () => (Percentage)(-1));
}

[Fact]
public void ShouldDefaultToZero()
{
Expand All @@ -30,12 +40,5 @@ public void ShouldHandleValueAbove100()
var percentage = new Percentage(200.0);
Assert.Equal("200%", percentage.ToString());
}

[Fact]
public void ShouldHandleNegativeValue()
{
var percentage = new Percentage(-25);
Assert.Equal("-25%", percentage.ToString());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -244,21 +244,5 @@ public void ShouldThrowExceptionWhenHeightIsNegative()
Assert.Throws<ArgumentException>("height", () => factory.Create(5, -1));
Assert.Throws<ArgumentException>("height", () => factory.Create(0, 0, 5, -1));
}

[Fact]
public void ShouldThrowExceptionWhenPercentageWidthIsNegative()
{
var factory = new MagickGeometryFactory();

Assert.Throws<ArgumentException>("percentageWidth", () => factory.Create(new Percentage(-1), new Percentage(10)));
}

[Fact]
public void ShouldThrowExceptionWhenPercentageHeightIsNegative()
{
var factory = new MagickGeometryFactory();

Assert.Throws<ArgumentException>("percentageHeight", () => factory.Create(new Percentage(10), new Percentage(-1)));
}
}
}
32 changes: 0 additions & 32 deletions tests/Magick.NET.Tests/MagickImageTests/TheColorizeMethod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,6 @@ public void ShouldThrowExceptionWhenColorIsNull()
Assert.Throws<ArgumentNullException>("color", () => image.Colorize(null, new Percentage(50)));
}

[Fact]
public void ShouldThrowExceptionWhenPercentageIsNegative()
{
using var image = new MagickImage();

Assert.Throws<ArgumentException>("alpha", () => image.Colorize(MagickColors.Purple, new Percentage(-1)));
}

[Fact]
public void ShouldColorizeTheImage()
{
Expand All @@ -49,30 +41,6 @@ public void ShouldThrowExceptionWhenColorIsNull()
Assert.Throws<ArgumentNullException>("color", () => image.Colorize(null, new Percentage(25), new Percentage(50), new Percentage(75)));
}

[Fact]
public void ShouldThrowExceptionWhenAlphaRedIsNegative()
{
using var image = new MagickImage();

Assert.Throws<ArgumentException>("alphaRed", () => image.Colorize(MagickColors.Purple, new Percentage(-1), new Percentage(50), new Percentage(75)));
}

[Fact]
public void ShouldThrowExceptionWhenAlphaGreenIsNegative()
{
using var image = new MagickImage();

Assert.Throws<ArgumentException>("alphaGreen", () => image.Colorize(MagickColors.Purple, new Percentage(25), new Percentage(-1), new Percentage(75)));
}

[Fact]
public void ShouldThrowExceptionWhenAlphaBlueIsNegative()
{
using var image = new MagickImage();

Assert.Throws<ArgumentException>("alphaBlue", () => image.Colorize(MagickColors.Purple, new Percentage(25), new Percentage(50), new Percentage(-1)));
}

[Fact]
public void ShouldColorizeTheImage()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,6 @@ public partial class MagickImageTests
{
public class TheContrastStretchMethod
{
[Fact]
public void ShouldThrowExceptionWhenPercentageIsNull()
{
using var image = new MagickImage();

Assert.Throws<ArgumentException>("blackPoint", () => image.ContrastStretch(new Percentage(-1)));
}

[Fact]
public void ShouldThrowExceptionWhenBlackPointIsNull()
{
using var image = new MagickImage();

Assert.Throws<ArgumentException>("blackPoint", () => image.ContrastStretch(new Percentage(-1), new Percentage(50)));
}

[Fact]
public void ShouldThrowExceptionWhenWhitePointIsNull()
{
using var image = new MagickImage();

Assert.Throws<ArgumentException>("whitePoint", () => image.ContrastStretch(new Percentage(50), new Percentage(-1)));
}

[Fact]
public void ShouldImproveTheContrast()
{
Expand Down
20 changes: 0 additions & 20 deletions tests/Magick.NET.Tests/MagickImageTests/TheDeskewMethod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,6 @@ public void ShouldThrowExceptionWhenSettingsIsNull()
Assert.Throws<ArgumentNullException>("settings", () => image.Deskew(null));
}

[Fact]
public void ShouldThrowExceptionWhenSettingsThresholdIsNegative()
{
var settings = new DeskewSettings
{
Threshold = new Percentage(-1),
};
using var image = new MagickImage();

Assert.Throws<ArgumentException>("settings", () => image.Deskew(settings));
}

[Fact]
public void ShouldThrowExceptionWhenThresholdIsNegative()
{
using var image = new MagickImage();

Assert.Throws<ArgumentException>("settings", () => image.Deskew(new Percentage(-1)));
}

[Fact]
public void ShouldDeskewTheImage()
{
Expand Down
Loading
Loading