diff --git a/src/ImageProcessorCore/Bootstrapper.cs b/src/ImageProcessorCore/Bootstrapper.cs
index 9e5ec39fd..2ddb64dcd 100644
--- a/src/ImageProcessorCore/Bootstrapper.cs
+++ b/src/ImageProcessorCore/Bootstrapper.cs
@@ -8,7 +8,6 @@ namespace ImageProcessorCore
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
- using System.Reflection;
using System.Threading.Tasks;
using Formats;
@@ -51,8 +50,8 @@ namespace ImageProcessorCore
///
/// Gets the collection of supported
///
- public IReadOnlyCollection ImageFormats =>
- new ReadOnlyCollection(this.imageFormats);
+ public IReadOnlyCollection ImageFormats => new ReadOnlyCollection(this.imageFormats);
+
///
/// Gets or sets the global parallel options for processing tasks in parallel.
diff --git a/src/ImageProcessorCore/Colors/Color.cs b/src/ImageProcessorCore/Colors/Color.cs
index 3a21c2130..80ee03e99 100644
--- a/src/ImageProcessorCore/Colors/Color.cs
+++ b/src/ImageProcessorCore/Colors/Color.cs
@@ -19,8 +19,24 @@ namespace ImageProcessorCore
///
public partial struct Color : IPackedVector, IEquatable
{
- private const float Max = 255F;
- private const float Min = 0F;
+ ///
+ /// The maximum byte value
+ ///
+ private const float MaxBytes = 255F;
+
+ ///
+ /// The minimum vector value
+ ///
+ private const float Zero = 0F;
+
+ ///
+ /// The maximum vector value
+ ///
+ private const float One = 1F;
+
+ ///
+ /// The packed value
+ ///
private uint packedValue;
///
@@ -34,6 +50,7 @@ namespace ImageProcessorCore
}
set
{
+ // AABBGGRR
this.packedValue = (uint)(this.packedValue & -0x100 | value);
}
}
@@ -50,7 +67,8 @@ namespace ImageProcessorCore
}
set
{
- this.packedValue = (uint)(this.packedValue & -0xff01 | (uint)value << 8);
+ // AABBGGRR
+ this.packedValue = (uint)(this.packedValue & -0xFF01 | (uint)value << 8);
}
}
@@ -65,7 +83,8 @@ namespace ImageProcessorCore
}
set
{
- this.packedValue = (uint)(this.packedValue & -0xff0001 | (uint)(value << 16));
+ // AABBGGRR
+ this.packedValue = (uint)(this.packedValue & -0xFF0001 | (uint)(value << 16));
}
}
@@ -80,7 +99,8 @@ namespace ImageProcessorCore
}
set
{
- this.packedValue = this.packedValue & 0xffffff | (uint)value << 24;
+ // AABBGGRR
+ this.packedValue = this.packedValue & 0xFFFFFF | (uint)value << 24;
}
}
@@ -217,40 +237,16 @@ namespace ImageProcessorCore
return left.packedValue != right.packedValue;
}
- ///
- public uint GetPackedValue()
- {
- return this.packedValue;
- }
-
- ///
- public void SetPackedValue(uint value)
- {
- this.packedValue = value;
- }
-
///
public void PackFromVector4(Vector4 vector)
{
this.packedValue = Pack(ref vector);
}
- ///
- public void PackFromBytes(byte x, byte y, byte z, byte w)
- {
- this.packedValue = (uint)(x | y << 8 | z << 16 | w << 24);
- }
-
///
public Vector4 ToVector4()
{
- return new Vector4(this.R, this.G, this.B, this.A) / 255F;
- }
-
- ///
- public byte[] ToBytes()
- {
- return new[] { this.R, this.G, this.B, this.A };
+ return new Vector4(this.R, this.G, this.B, this.A) / MaxBytes;
}
///
@@ -308,12 +304,13 @@ namespace ImageProcessorCore
/// The z-component
/// The w-component
/// The
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint Pack(float x, float y, float z, float w)
{
- return (uint)((byte)Math.Round(x.Clamp(0, 1) * Max)
- | ((byte)Math.Round(y.Clamp(0, 1) * Max) << 8)
- | (byte)Math.Round(z.Clamp(0, 1) * Max) << 16
- | (byte)Math.Round(w.Clamp(0, 1) * Max) << 24);
+ return (uint)((byte)Math.Round(x.Clamp(Zero, One) * MaxBytes)
+ | ((byte)Math.Round(y.Clamp(Zero, One) * MaxBytes) << 8)
+ | (byte)Math.Round(z.Clamp(Zero, One) * MaxBytes) << 16
+ | (byte)Math.Round(w.Clamp(Zero, One) * MaxBytes) << 24);
}
///
diff --git a/src/ImageProcessorCore/Colors/Colorspaces/IAlmostEquatable.cs b/src/ImageProcessorCore/Colors/Colorspaces/IAlmostEquatable.cs
index 97f57c21a..134b19014 100644
--- a/src/ImageProcessorCore/Colors/Colorspaces/IAlmostEquatable.cs
+++ b/src/ImageProcessorCore/Colors/Colorspaces/IAlmostEquatable.cs
@@ -12,8 +12,9 @@ namespace ImageProcessorCore
/// a type-specific method for determining approximate equality of instances.
///
/// The type of objects to compare.
- /// The object specifying the type to specify precision with.
- public interface IAlmostEquatable where TPacked : struct, IComparable
+ /// The object specifying the type to specify precision with.
+ public interface IAlmostEquatable
+ where TPrecision : struct, IComparable
{
///
/// Indicates whether the current object is equal to another object of the same type
@@ -24,6 +25,6 @@ namespace ImageProcessorCore
///
/// true if the current object is equal to the other parameter; otherwise, false.
///
- bool AlmostEquals(TColor other, TPacked precision);
+ bool AlmostEquals(TColor other, TPrecision precision);
}
}
diff --git a/src/ImageProcessorCore/Colors/PackedVector/IPackedVector.cs b/src/ImageProcessorCore/Colors/PackedVector/IPackedVector.cs
index a0d71e4e2..2deb378f4 100644
--- a/src/ImageProcessorCore/Colors/PackedVector/IPackedVector.cs
+++ b/src/ImageProcessorCore/Colors/PackedVector/IPackedVector.cs
@@ -29,28 +29,11 @@ namespace ImageProcessorCore
/// The vector to create the packed representation from.
void PackFromVector4(Vector4 vector);
- /////
- ///// Sets the packed representation from a .
- /////
- ///// The x-component to create the packed representation from.
- ///// The y-component to create the packed representation from.
- ///// The z-component to create the packed representation from.
- ///// The w-component to create the packed representation from.
- //void PackFromBytes(byte x, byte y, byte z, byte w);
-
///
/// Expands the packed representation into a .
/// The vector components are typically expanded in least to greatest significance order.
///
/// The .
Vector4 ToVector4();
-
- /////
- ///// Expands the packed representation into a .
- ///// The bytes are typically expanded in least to greatest significance order.
- ///// Red -> Green -> Blue -> Alpha
- /////
- ///// The .
- //byte[] ToBytes();
}
}
diff --git a/src/ImageProcessorCore/Common/Extensions/ByteExtensions.cs b/src/ImageProcessorCore/Common/Extensions/ByteExtensions.cs
index bee549c0f..f5da2252b 100644
--- a/src/ImageProcessorCore/Common/Extensions/ByteExtensions.cs
+++ b/src/ImageProcessorCore/Common/Extensions/ByteExtensions.cs
@@ -20,7 +20,7 @@ namespace ImageProcessorCore
/// The number of bits per value.
/// The resulting array. Is never null.
/// is null.
- /// is less than or equals than zero.
+ /// is less than or equals than zero.
public static byte[] ToArrayByBitsLength(this byte[] bytes, int bits)
{
Guard.NotNull(bytes, "bytes");
diff --git a/src/ImageProcessorCore/Common/Helpers/Guard.cs b/src/ImageProcessorCore/Common/Helpers/Guard.cs
index 6940a460e..1e9b3ea23 100644
--- a/src/ImageProcessorCore/Common/Helpers/Guard.cs
+++ b/src/ImageProcessorCore/Common/Helpers/Guard.cs
@@ -1,16 +1,8 @@
-// --------------------------------------------------------------------------------------------------------------------
-//
-// Copyright (c) James Jackson-South and contributors.
-// Licensed under the Apache License, Version 2.0.
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
//
-//
-// Provides methods to protect against invalid parameters.
-//
-// --------------------------------------------------------------------------------------------------------------------
-using System.Runtime.CompilerServices;
-
-[assembly: InternalsVisibleTo("ImageProcessorCore.Tests")]
namespace ImageProcessorCore
{
using System;
@@ -26,23 +18,15 @@ namespace ImageProcessorCore
/// Verifies, that the method parameter with specified object value is not null
/// and throws an exception if it is found to be so.
///
- ///
- /// The target object, which cannot be null.
- ///
- ///
- /// The name of the parameter that is to be checked.
- ///
- ///
- /// The error message, if any to add to the exception.
- ///
- ///
- /// is null
- ///
+ /// The target object, which cannot be null.
+ /// The name of the parameter that is to be checked.
+ /// The error message, if any to add to the exception.
+ /// is null
public static void NotNull(object target, string parameterName, string message = "")
{
if (target == null)
{
- if (string.IsNullOrWhiteSpace(message))
+ if (!string.IsNullOrWhiteSpace(message))
{
throw new ArgumentNullException(parameterName, message);
}
@@ -58,13 +42,8 @@ namespace ImageProcessorCore
///
/// The target string, which should be checked against being null or empty.
/// Name of the parameter.
- ///
- /// is null.
- ///
- ///
- /// is
- /// empty or contains only blanks.
- ///
+ /// is null.
+ /// is empty or contains only blanks.
public static void NotNullOrEmpty(string target, string parameterName)
{
if (target == null)
@@ -94,9 +73,7 @@ namespace ImageProcessorCore
{
if (value.CompareTo(max) >= 0)
{
- throw new ArgumentOutOfRangeException(
- parameterName,
- $"Value must be less than {max}.");
+ throw new ArgumentOutOfRangeException(parameterName, $"Value must be less than {max}.");
}
}
@@ -116,9 +93,7 @@ namespace ImageProcessorCore
{
if (value.CompareTo(max) > 0)
{
- throw new ArgumentOutOfRangeException(
- parameterName,
- $"Value must be less than or equal to {max}.");
+ throw new ArgumentOutOfRangeException(parameterName, $"Value must be less than or equal to {max}.");
}
}
@@ -134,7 +109,7 @@ namespace ImageProcessorCore
/// is less than the minimum value.
///
public static void MustBeGreaterThan(TValue value, TValue min, string parameterName)
- where TValue : IComparable
+ where TValue : IComparable
{
if (value.CompareTo(min) <= 0)
{
@@ -156,13 +131,11 @@ namespace ImageProcessorCore
/// is less than the minimum value.
///
public static void MustBeGreaterThanOrEqualTo(TValue value, TValue min, string parameterName)
- where TValue : IComparable
+ where TValue : IComparable
{
if (value.CompareTo(min) < 0)
{
- throw new ArgumentOutOfRangeException(
- parameterName,
- $"Value must be greater than or equal to {min}.");
+ throw new ArgumentOutOfRangeException(parameterName, $"Value must be greater than or equal to {min}.");
}
}
@@ -179,13 +152,11 @@ namespace ImageProcessorCore
/// is less than the minimum value of greater than the maximum value.
///
public static void MustBeBetweenOrEqualTo(TValue value, TValue min, TValue max, string parameterName)
- where TValue : IComparable
+ where TValue : IComparable
{
if (value.CompareTo(min) < 0 || value.CompareTo(max) > 0)
{
- throw new ArgumentOutOfRangeException(
- parameterName,
- $"Value must be greater than or equal to {min} and less than or equal to {max}.");
+ throw new ArgumentOutOfRangeException(parameterName, $"Value must be greater than or equal to {min} and less than or equal to {max}.");
}
}
@@ -203,18 +174,13 @@ namespace ImageProcessorCore
/// The error message, if any to add to the exception.
///
///
- /// is null
+ /// is false
///
- public static void IsTrue(bool target, string parameterName, string message = "")
+ public static void IsTrue(bool target, string parameterName, string message)
{
if (!target)
{
- if (string.IsNullOrWhiteSpace(message))
- {
- throw new ArgumentException(parameterName, message);
- }
-
- throw new ArgumentException(parameterName);
+ throw new ArgumentException(message, parameterName);
}
}
@@ -222,28 +188,17 @@ namespace ImageProcessorCore
/// Verifies, that the method parameter with specified target value is false
/// and throws an exception if it is found to be so.
///
- ///
- /// The target value, which cannot be true.
- ///
- ///
- /// The name of the parameter that is to be checked.
- ///
- ///
- /// The error message, if any to add to the exception.
- ///
+ /// The target value, which cannot be true.
+ /// The name of the parameter that is to be checked.
+ /// The error message, if any to add to the exception.
///
- /// is null
+ /// is true
///
- public static void IsFalse(bool target, string parameterName, string message = "")
+ public static void IsFalse(bool target, string parameterName, string message)
{
if (target)
{
- if (string.IsNullOrWhiteSpace(message))
- {
- throw new ArgumentException(parameterName, message);
- }
-
- throw new ArgumentException(parameterName);
+ throw new ArgumentException(message, parameterName);
}
}
}
diff --git a/src/ImageProcessorCore/Filters/Blend.cs b/src/ImageProcessorCore/Filters/Blend.cs
index 77b65cf20..215bd23eb 100644
--- a/src/ImageProcessorCore/Filters/Blend.cs
+++ b/src/ImageProcessorCore/Filters/Blend.cs
@@ -1,7 +1,7 @@
//
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
-// -------------------------------------------------------------------------------------------------------------------
+//
namespace ImageProcessorCore
{
@@ -15,10 +15,10 @@ namespace ImageProcessorCore
///
/// Combines the given image together with the current one by blending their pixels.
///
- /// The image this method extends.
- /// The image to blend with the currently processing image.
/// The pixel format.
/// The packed format. uint, long, float.
+ /// The image this method extends.
+ /// The image to blend with the currently processing image.
/// The opacity of the image image to blend. Must be between 0 and 100.
/// A delegate which is called as progress is made processing the image.
/// The .
diff --git a/src/ImageProcessorCore/Filters/BoxBlur.cs b/src/ImageProcessorCore/Filters/BoxBlur.cs
index acbd0d895..f4a0ce238 100644
--- a/src/ImageProcessorCore/Filters/BoxBlur.cs
+++ b/src/ImageProcessorCore/Filters/BoxBlur.cs
@@ -15,8 +15,8 @@ namespace ImageProcessorCore
///
/// Applies a box blur to the image.
///
- /// The pixel format.
- /// The packed format. uint, long, float.
+ /// The pixel format.
+ /// The packed format. long, float.
/// The image this method extends.
/// The 'radius' value representing the size of the area to sample.
/// A delegate which is called as progress is made processing the image.
@@ -31,8 +31,8 @@ namespace ImageProcessorCore
///
/// Applies a box blur to the image.
///
- /// The pixel format.
- /// The packed format. uint, long, float.
+ /// The pixel format.
+ /// The packed format. long, float.
/// The image this method extends.
/// The 'radius' value representing the size of the area to sample.
///
diff --git a/src/ImageProcessorCore/Filters/DetectEdges.cs b/src/ImageProcessorCore/Filters/DetectEdges.cs
index d306badbb..60006ea72 100644
--- a/src/ImageProcessorCore/Filters/DetectEdges.cs
+++ b/src/ImageProcessorCore/Filters/DetectEdges.cs
@@ -29,7 +29,7 @@ namespace ImageProcessorCore
}
///
- /// Detects any edges within the image. Uses the filter
+ /// Detects any edges within the image. Uses the filter
/// operating in Grayscale mode.
///
/// The pixel format.
diff --git a/src/ImageProcessorCore/Filters/Invert.cs b/src/ImageProcessorCore/Filters/Invert.cs
index e1f59d8d3..ed7124662 100644
--- a/src/ImageProcessorCore/Filters/Invert.cs
+++ b/src/ImageProcessorCore/Filters/Invert.cs
@@ -1,20 +1,22 @@
//
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
-// -------------------------------------------------------------------------------------------------------------------
+//
namespace ImageProcessorCore
{
using Processors;
///
- /// Extension methods for the type.
+ /// Extension methods for the type.
///
public static partial class ImageExtensions
{
///
/// Inverts the colors of the image.
///
+ /// The pixel format.
+ /// The packed format. uint, long, float.
/// The image this method extends.
/// A delegate which is called as progress is made processing the image.
/// The .
@@ -28,6 +30,8 @@ namespace ImageProcessorCore
///
/// Inverts the colors of the image.
///
+ /// The pixel format.
+ /// The packed format. uint, long, float.
/// The image this method extends.
///
/// The structure that specifies the portion of the image object to alter.
diff --git a/src/ImageProcessorCore/Filters/Kodachrome.cs b/src/ImageProcessorCore/Filters/Kodachrome.cs
index 9a27f2010..7310703b0 100644
--- a/src/ImageProcessorCore/Filters/Kodachrome.cs
+++ b/src/ImageProcessorCore/Filters/Kodachrome.cs
@@ -10,6 +10,8 @@ namespace ImageProcessorCore
///
/// Extension methods for the type.
///
+ /// The pixel format.
+ /// The packed format. uint, long, float.
public static partial class ImageExtensions
{
///
diff --git a/src/ImageProcessorCore/Filters/Pixelate.cs b/src/ImageProcessorCore/Filters/Pixelate.cs
index 32b443881..a9b7f63af 100644
--- a/src/ImageProcessorCore/Filters/Pixelate.cs
+++ b/src/ImageProcessorCore/Filters/Pixelate.cs
@@ -11,13 +11,13 @@ namespace ImageProcessorCore
///
/// Extension methods for the type.
///
- /// The pixel format.
- /// The packed format. uint, long, float.
public static partial class ImageExtensions
{
///
/// Pixelates and image with the given pixel size.
///
+ /// The pixel format.
+ /// The packed format. uint, long, float.
/// The image this method extends.
/// The size of the pixels.
/// A delegate which is called as progress is made processing the image.
@@ -32,6 +32,8 @@ namespace ImageProcessorCore
///
/// Pixelates and image with the given pixel size.
///
+ /// The pixel format.
+ /// The packed format. uint, long, float.
/// The image this method extends.
/// The size of the pixels.
///
diff --git a/src/ImageProcessorCore/Filters/Processors/AlphaProcessor.cs b/src/ImageProcessorCore/Filters/Processors/AlphaProcessor.cs
index 2b04b6a33..9572cf63b 100644
--- a/src/ImageProcessorCore/Filters/Processors/AlphaProcessor.cs
+++ b/src/ImageProcessorCore/Filters/Processors/AlphaProcessor.cs
@@ -22,7 +22,7 @@ namespace ImageProcessorCore.Processors
/// Initializes a new instance of the class.
///
/// The percentage to adjust the opacity of the image. Must be between 0 and 100.
- ///
+ ///
/// is less than 0 or is greater than 100.
///
public AlphaProcessor(int percent)
diff --git a/src/ImageProcessorCore/Filters/Processors/BackgroundColorProcessor.cs b/src/ImageProcessorCore/Filters/Processors/BackgroundColorProcessor.cs
index b5a22e796..cb3173385 100644
--- a/src/ImageProcessorCore/Filters/Processors/BackgroundColorProcessor.cs
+++ b/src/ImageProcessorCore/Filters/Processors/BackgroundColorProcessor.cs
@@ -24,7 +24,7 @@ namespace ImageProcessorCore.Processors
///
/// Initializes a new instance of the class.
///
- /// The to set the background color to.
+ /// The to set the background color to.
public BackgroundColorProcessor(TColor color)
{
this.Value = color;
diff --git a/src/ImageProcessorCore/Filters/Processors/Binarization/BinaryThresholdProcessor.cs b/src/ImageProcessorCore/Filters/Processors/Binarization/BinaryThresholdProcessor.cs
index bb6845878..4b4f67b50 100644
--- a/src/ImageProcessorCore/Filters/Processors/Binarization/BinaryThresholdProcessor.cs
+++ b/src/ImageProcessorCore/Filters/Processors/Binarization/BinaryThresholdProcessor.cs
@@ -22,7 +22,7 @@ namespace ImageProcessorCore.Processors
/// Initializes a new instance of the class.
///
/// The threshold to split the image. Must be between 0 and 1.
- ///
+ ///
/// is less than 0 or is greater than 1.
///
public BinaryThresholdProcessor(float threshold)
@@ -111,4 +111,4 @@ namespace ImageProcessorCore.Processors
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageProcessorCore/Filters/Processors/BlendProcessor.cs b/src/ImageProcessorCore/Filters/Processors/BlendProcessor.cs
index 1cf51c1d1..1b333b6f0 100644
--- a/src/ImageProcessorCore/Filters/Processors/BlendProcessor.cs
+++ b/src/ImageProcessorCore/Filters/Processors/BlendProcessor.cs
@@ -24,7 +24,7 @@ namespace ImageProcessorCore.Processors
private readonly ImageBase blend;
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
///
/// The image to blend with the currently processing image.
diff --git a/src/ImageProcessorCore/Filters/Processors/BrightnessProcessor.cs b/src/ImageProcessorCore/Filters/Processors/BrightnessProcessor.cs
index f1259dac5..f87e514e9 100644
--- a/src/ImageProcessorCore/Filters/Processors/BrightnessProcessor.cs
+++ b/src/ImageProcessorCore/Filters/Processors/BrightnessProcessor.cs
@@ -22,7 +22,7 @@ namespace ImageProcessorCore.Processors
/// Initializes a new instance of the class.
///
/// The new brightness of the image. Must be between -100 and 100.
- ///
+ ///
/// is less than -100 or is greater than 100.
///
public BrightnessProcessor(int brightness)
diff --git a/src/ImageProcessorCore/Filters/Processors/ColorMatrix/HueProcessor.cs b/src/ImageProcessorCore/Filters/Processors/ColorMatrix/HueProcessor.cs
index a497f5bd4..afe6dbca9 100644
--- a/src/ImageProcessorCore/Filters/Processors/ColorMatrix/HueProcessor.cs
+++ b/src/ImageProcessorCore/Filters/Processors/ColorMatrix/HueProcessor.cs
@@ -9,7 +9,7 @@ namespace ImageProcessorCore.Processors
using System.Numerics;
///
- /// An to change the hue of an .
+ /// An to change the hue of an .
///
/// The pixel format.
/// The packed format. uint, long, float.
@@ -18,12 +18,7 @@ namespace ImageProcessorCore.Processors
where TPacked : struct
{
///
- /// The used to alter the image.
- ///
- private Matrix4x4 matrix;
-
- ///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// The new brightness of the image. Must be between -100 and 100.
public HueProcessor(float angle)
@@ -67,7 +62,7 @@ namespace ImageProcessorCore.Processors
M33 = (float)(lumB + (cosradians * oneMinusLumB) + (sinradians * lumB))
};
- this.matrix = matrix4X4;
+ this.Matrix = matrix4X4;
}
///
@@ -76,7 +71,7 @@ namespace ImageProcessorCore.Processors
public float Angle { get; }
///
- public override Matrix4x4 Matrix => this.matrix;
+ public override Matrix4x4 Matrix { get; }
///
public override bool Compand => false;
diff --git a/src/ImageProcessorCore/Filters/Processors/ColorMatrix/IColorMatrixFilter.cs b/src/ImageProcessorCore/Filters/Processors/ColorMatrix/IColorMatrixFilter.cs
index cb4c3c36a..f1f6377ef 100644
--- a/src/ImageProcessorCore/Filters/Processors/ColorMatrix/IColorMatrixFilter.cs
+++ b/src/ImageProcessorCore/Filters/Processors/ColorMatrix/IColorMatrixFilter.cs
@@ -11,6 +11,8 @@ namespace ImageProcessorCore.Processors
/// Encapsulates properties and methods for creating processors that utilize a matrix to
/// alter the image pixels.
///
+ /// The pixel format.
+ /// The packed format. uint, long, float.
public interface IColorMatrixFilter : IImageProcessor
where TColor : IPackedVector
where TPacked : struct
diff --git a/src/ImageProcessorCore/Filters/Processors/ColorMatrix/PolaroidProcessor.cs b/src/ImageProcessorCore/Filters/Processors/ColorMatrix/PolaroidProcessor.cs
index b28838637..65bc68aea 100644
--- a/src/ImageProcessorCore/Filters/Processors/ColorMatrix/PolaroidProcessor.cs
+++ b/src/ImageProcessorCore/Filters/Processors/ColorMatrix/PolaroidProcessor.cs
@@ -45,4 +45,4 @@ namespace ImageProcessorCore.Processors
new GlowProcessor { GlowColor = packedG, Radius = target.Width / 4F }.Apply(target, target, sourceRectangle);
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageProcessorCore/Filters/Processors/ColorMatrix/SaturationProcessor.cs b/src/ImageProcessorCore/Filters/Processors/ColorMatrix/SaturationProcessor.cs
index ae031fed9..37612357a 100644
--- a/src/ImageProcessorCore/Filters/Processors/ColorMatrix/SaturationProcessor.cs
+++ b/src/ImageProcessorCore/Filters/Processors/ColorMatrix/SaturationProcessor.cs
@@ -8,7 +8,7 @@ namespace ImageProcessorCore.Processors
using System.Numerics;
///
- /// An to change the saturation of an .
+ /// An to change the saturation of an .
///
/// The pixel format.
/// The packed format. uint, long, float.
@@ -17,28 +17,16 @@ namespace ImageProcessorCore.Processors
where TPacked : struct
{
///
- /// The saturation to be applied to the image.
- ///
- private readonly int saturation;
-
- ///
- /// The used to alter the image.
- ///
- private Matrix4x4 matrix;
-
- ///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// The new saturation of the image. Must be between -100 and 100.
- ///
+ ///
/// is less than -100 or is greater than 100.
///
public SaturationProcessor(int saturation)
{
Guard.MustBeBetweenOrEqualTo(saturation, -100, 100, nameof(saturation));
- this.saturation = saturation;
-
- float saturationFactor = this.saturation / 100f;
+ float saturationFactor = saturation / 100f;
// Stop at -1 to prevent inversion.
saturationFactor++;
@@ -65,10 +53,10 @@ namespace ImageProcessorCore.Processors
M33 = saturationComplementB + saturationFactor,
};
- this.matrix = matrix4X4;
+ this.Matrix = matrix4X4;
}
///
- public override Matrix4x4 Matrix => this.matrix;
+ public override Matrix4x4 Matrix { get; }
}
}
diff --git a/src/ImageProcessorCore/Filters/Processors/ColorMatrix/SepiaProcessor.cs b/src/ImageProcessorCore/Filters/Processors/ColorMatrix/SepiaProcessor.cs
index 6a4b2c880..040d48884 100644
--- a/src/ImageProcessorCore/Filters/Processors/ColorMatrix/SepiaProcessor.cs
+++ b/src/ImageProcessorCore/Filters/Processors/ColorMatrix/SepiaProcessor.cs
@@ -34,4 +34,4 @@ namespace ImageProcessorCore.Processors
///
public override bool Compand => false;
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageProcessorCore/Filters/Processors/ContrastProcessor.cs b/src/ImageProcessorCore/Filters/Processors/ContrastProcessor.cs
index 91a7e4a12..54a9e10cc 100644
--- a/src/ImageProcessorCore/Filters/Processors/ContrastProcessor.cs
+++ b/src/ImageProcessorCore/Filters/Processors/ContrastProcessor.cs
@@ -12,17 +12,17 @@ namespace ImageProcessorCore.Processors
///
/// An to change the contrast of an .
///
- /// The pixel format.
- /// The packed format. uint, long, float.
+ /// The pixel format.
+ /// The packed format. long, float.
public class ContrastProcessor : ImageProcessor
where TColor : IPackedVector
where TPacked : struct
{
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// The new contrast of the image. Must be between -100 and 100.
- ///
+ ///
/// is less than -100 or is greater than 100.
///
public ContrastProcessor(int contrast)
diff --git a/src/ImageProcessorCore/Filters/Processors/Convolution/BoxBlurProcessor.cs b/src/ImageProcessorCore/Filters/Processors/Convolution/BoxBlurProcessor.cs
index f8c2d9109..1b8430f5f 100644
--- a/src/ImageProcessorCore/Filters/Processors/Convolution/BoxBlurProcessor.cs
+++ b/src/ImageProcessorCore/Filters/Processors/Convolution/BoxBlurProcessor.cs
@@ -30,7 +30,7 @@ namespace ImageProcessorCore.Processors
private float[,] kernelX;
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
///
/// The 'radius' value representing the size of the area to sample.
diff --git a/src/ImageProcessorCore/Filters/Processors/Convolution/ConvolutionFilter.cs b/src/ImageProcessorCore/Filters/Processors/Convolution/ConvolutionFilter.cs
index dfc026bae..da0c11df5 100644
--- a/src/ImageProcessorCore/Filters/Processors/Convolution/ConvolutionFilter.cs
+++ b/src/ImageProcessorCore/Filters/Processors/Convolution/ConvolutionFilter.cs
@@ -11,6 +11,8 @@ namespace ImageProcessorCore.Processors
///
/// Defines a filter that uses a 2 dimensional matrix to perform convolution against an image.
///
+ /// The pixel format.
+ /// The packed format. uint, long, float.
public abstract class ConvolutionFilter : ImageProcessor
where TColor : IPackedVector
where TPacked : struct
diff --git a/src/ImageProcessorCore/Filters/Processors/Convolution/EdgeDetection/EdgeDetector2DFilter.cs b/src/ImageProcessorCore/Filters/Processors/Convolution/EdgeDetection/EdgeDetector2DFilter.cs
index 6475ad7cb..34a589630 100644
--- a/src/ImageProcessorCore/Filters/Processors/Convolution/EdgeDetection/EdgeDetector2DFilter.cs
+++ b/src/ImageProcessorCore/Filters/Processors/Convolution/EdgeDetection/EdgeDetector2DFilter.cs
@@ -9,6 +9,8 @@ namespace ImageProcessorCore.Processors
/// Defines a filter that detects edges within an image using two
/// one-dimensional matrices.
///
+ /// The pixel format.
+ /// The packed format. uint, long, float.
public abstract class EdgeDetector2DFilter : Convolution2DFilter, IEdgeDetectorFilter
where TColor : IPackedVector
where TPacked : struct
diff --git a/src/ImageProcessorCore/Filters/Processors/Convolution/EdgeDetection/EdgeDetectorFilter.cs b/src/ImageProcessorCore/Filters/Processors/Convolution/EdgeDetection/EdgeDetectorFilter.cs
index 2d221664d..04cd2cddd 100644
--- a/src/ImageProcessorCore/Filters/Processors/Convolution/EdgeDetection/EdgeDetectorFilter.cs
+++ b/src/ImageProcessorCore/Filters/Processors/Convolution/EdgeDetection/EdgeDetectorFilter.cs
@@ -9,6 +9,8 @@ namespace ImageProcessorCore.Processors
/// Defines a filter that detects edges within an image using a single
/// two dimensional matrix.
///
+ /// The pixel format.
+ /// The packed format. uint, long, float.
public abstract class EdgeDetectorFilter : ConvolutionFilter, IEdgeDetectorFilter
where TColor : IPackedVector
where TPacked : struct
diff --git a/src/ImageProcessorCore/Filters/Processors/Convolution/EdgeDetection/IEdgeDetectorFilter.cs b/src/ImageProcessorCore/Filters/Processors/Convolution/EdgeDetection/IEdgeDetectorFilter.cs
index e101612b6..620db328e 100644
--- a/src/ImageProcessorCore/Filters/Processors/Convolution/EdgeDetection/IEdgeDetectorFilter.cs
+++ b/src/ImageProcessorCore/Filters/Processors/Convolution/EdgeDetection/IEdgeDetectorFilter.cs
@@ -8,6 +8,8 @@ namespace ImageProcessorCore.Processors
///
/// Provides properties and methods allowing the detection of edges within an image.
///
+ /// The pixel format.
+ /// The packed format. uint, long, float.
public interface IEdgeDetectorFilter : IImageProcessor, IEdgeDetectorFilter
where TColor : IPackedVector
where TPacked : struct
diff --git a/src/ImageProcessorCore/Filters/Processors/Convolution/GuassianBlurProcessor.cs b/src/ImageProcessorCore/Filters/Processors/Convolution/GuassianBlurProcessor.cs
index 7ab5fe4fb..7a9b0137f 100644
--- a/src/ImageProcessorCore/Filters/Processors/Convolution/GuassianBlurProcessor.cs
+++ b/src/ImageProcessorCore/Filters/Processors/Convolution/GuassianBlurProcessor.cs
@@ -37,7 +37,7 @@ namespace ImageProcessorCore.Processors
private float[,] kernelX;
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// The 'sigma' value representing the weight of the blur.
public GuassianBlurProcessor(float sigma = 3f)
@@ -47,7 +47,7 @@ namespace ImageProcessorCore.Processors
}
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
///
/// The 'radius' value representing the size of the area to sample.
@@ -59,7 +59,7 @@ namespace ImageProcessorCore.Processors
}
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
///
/// The 'sigma' value representing the weight of the blur.
diff --git a/src/ImageProcessorCore/Filters/Processors/Convolution/GuassianSharpenProcessor.cs b/src/ImageProcessorCore/Filters/Processors/Convolution/GuassianSharpenProcessor.cs
index 2c290f2df..18704faf1 100644
--- a/src/ImageProcessorCore/Filters/Processors/Convolution/GuassianSharpenProcessor.cs
+++ b/src/ImageProcessorCore/Filters/Processors/Convolution/GuassianSharpenProcessor.cs
@@ -37,7 +37,7 @@ namespace ImageProcessorCore.Processors
private float[,] kernelX;
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
///
/// The 'sigma' value representing the weight of the sharpening.
@@ -49,7 +49,7 @@ namespace ImageProcessorCore.Processors
}
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
///
/// The 'radius' value representing the size of the area to sample.
@@ -61,7 +61,7 @@ namespace ImageProcessorCore.Processors
}
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
///
/// The 'sigma' value representing the weight of the sharpen.
diff --git a/src/ImageProcessorCore/Filters/Processors/GlowProcessor.cs b/src/ImageProcessorCore/Filters/Processors/GlowProcessor.cs
index ee6b07d17..10a68ffcf 100644
--- a/src/ImageProcessorCore/Filters/Processors/GlowProcessor.cs
+++ b/src/ImageProcessorCore/Filters/Processors/GlowProcessor.cs
@@ -15,11 +15,11 @@ namespace ImageProcessorCore.Processors
/// The pixel format.
/// The packed format. uint, long, float.
public class GlowProcessor : ImageProcessor
- where TColor : IPackedVector
- where TPacked : struct
+ where TColor : IPackedVector
+ where TPacked : struct
{
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
public GlowProcessor()
{
diff --git a/src/ImageProcessorCore/Filters/Processors/PixelateProcessor.cs b/src/ImageProcessorCore/Filters/Processors/PixelateProcessor.cs
index 4e5c63ed4..300081050 100644
--- a/src/ImageProcessorCore/Filters/Processors/PixelateProcessor.cs
+++ b/src/ImageProcessorCore/Filters/Processors/PixelateProcessor.cs
@@ -19,7 +19,7 @@ namespace ImageProcessorCore.Processors
where TPacked : struct
{
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// The size of the pixels. Must be greater than 0.
///
@@ -110,4 +110,4 @@ namespace ImageProcessorCore.Processors
}
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageProcessorCore/Filters/Processors/VignetteProcessor.cs b/src/ImageProcessorCore/Filters/Processors/VignetteProcessor.cs
index c6e8cf35e..142f20e6b 100644
--- a/src/ImageProcessorCore/Filters/Processors/VignetteProcessor.cs
+++ b/src/ImageProcessorCore/Filters/Processors/VignetteProcessor.cs
@@ -96,5 +96,4 @@ namespace ImageProcessorCore.Processors
}
}
}
-}
-
+}
\ No newline at end of file
diff --git a/src/ImageProcessorCore/Filters/Sepia.cs b/src/ImageProcessorCore/Filters/Sepia.cs
index 750d3016f..126c0d92a 100644
--- a/src/ImageProcessorCore/Filters/Sepia.cs
+++ b/src/ImageProcessorCore/Filters/Sepia.cs
@@ -55,4 +55,4 @@ namespace ImageProcessorCore
}
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageProcessorCore/Formats/Bmp/BmpDecoder.cs b/src/ImageProcessorCore/Formats/Bmp/BmpDecoder.cs
index c87de4cc0..2f2484554 100644
--- a/src/ImageProcessorCore/Formats/Bmp/BmpDecoder.cs
+++ b/src/ImageProcessorCore/Formats/Bmp/BmpDecoder.cs
@@ -71,8 +71,8 @@ namespace ImageProcessorCore.Formats
///
public void Decode(Image image, Stream stream)
- where TColor : IPackedVector
- where TPacked : struct
+ where TColor : IPackedVector
+ where TPacked : struct
{
Guard.NotNull(image, "image");
Guard.NotNull(stream, "stream");
diff --git a/src/ImageProcessorCore/Formats/Bmp/BmpDecoderCore.cs b/src/ImageProcessorCore/Formats/Bmp/BmpDecoderCore.cs
index cd3e0e56e..d353e5723 100644
--- a/src/ImageProcessorCore/Formats/Bmp/BmpDecoderCore.cs
+++ b/src/ImageProcessorCore/Formats/Bmp/BmpDecoderCore.cs
@@ -128,8 +128,7 @@ namespace ImageProcessorCore.Formats
case BmpCompression.RGB:
if (this.infoHeader.HeaderSize != 40)
{
- throw new ImageFormatException(
- $"Header Size value '{this.infoHeader.HeaderSize}' is not valid.");
+ throw new ImageFormatException($"Header Size value '{this.infoHeader.HeaderSize}' is not valid.");
}
if (this.infoHeader.BitsPerPixel == 32)
@@ -190,7 +189,7 @@ namespace ImageProcessorCore.Formats
///
/// The pixel format.
/// The packed format. uint, long, float.
- /// The image data to assign the palette to.
+ /// The image data to assign the palette to.
/// The containing the colors.
/// The width of the bitmap.
/// The height of the bitmap.
@@ -255,7 +254,7 @@ namespace ImageProcessorCore.Formats
///
/// The pixel format.
/// The packed format. uint, long, float.
- /// The image data to assign the palette to.
+ /// The image data to assign the palette to.
/// The width of the bitmap.
/// The height of the bitmap.
/// Whether the bitmap is inverted.
@@ -306,7 +305,7 @@ namespace ImageProcessorCore.Formats
///
/// The pixel format.
/// The packed format. uint, long, float.
- /// The image data to assign the palette to.
+ /// The image data to assign the palette to.
/// The width of the bitmap.
/// The height of the bitmap.
/// Whether the bitmap is inverted.
@@ -346,7 +345,7 @@ namespace ImageProcessorCore.Formats
///
/// The pixel format.
/// The packed format. uint, long, float.
- /// The image data to assign the palette to.
+ /// The image data to assign the palette to.
/// The width of the bitmap.
/// The height of the bitmap.
/// Whether the bitmap is inverted.
diff --git a/src/ImageProcessorCore/Formats/Bmp/BmpEncoderCore.cs b/src/ImageProcessorCore/Formats/Bmp/BmpEncoderCore.cs
index 441ffc4a3..edd663997 100644
--- a/src/ImageProcessorCore/Formats/Bmp/BmpEncoderCore.cs
+++ b/src/ImageProcessorCore/Formats/Bmp/BmpEncoderCore.cs
@@ -27,8 +27,8 @@ namespace ImageProcessorCore.Formats
///
/// Encodes the image to the specified stream from the .
///
- /// The pixel format.
- /// The packed format. uint, long, float.
+ /// The pixel format.
+ /// The packed format. long, float.
/// The to encode from.
/// The to encode the image data to.
/// The
@@ -134,11 +134,11 @@ namespace ImageProcessorCore.Formats
switch (this.bmpBitsPerPixel)
{
case BmpBitsPerPixel.Pixel32:
- this.Write32Bit(writer, pixels);
+ this.Write32Bit(writer, pixels);
break;
case BmpBitsPerPixel.Pixel24:
- this.Write24Bit(writer, pixels);
+ this.Write24Bit(writer, pixels);
break;
}
}
@@ -150,7 +150,7 @@ namespace ImageProcessorCore.Formats
/// The pixel format.
/// The packed format. uint, long, float.
/// The containing the stream to write to.
- /// The containing pixel data.
+ /// The containing pixel data.
private void Write32Bit(EndianBinaryWriter writer, PixelAccessor pixels)
where TColor : IPackedVector
where TPacked : struct
@@ -176,7 +176,8 @@ namespace ImageProcessorCore.Formats
/// Writes the 24bit color palette to the stream.
///
/// The pixel format.
- /// The packed format. uint, long, float./// The containing the stream to write to.
+ /// The packed format. uint, long, float.
+ /// The containing the stream to write to.
/// The containing pixel data.
private void Write24Bit(EndianBinaryWriter writer, PixelAccessor pixels)
where TColor : IPackedVector
diff --git a/src/ImageProcessorCore/Formats/Gif/GifDecoderCore.cs b/src/ImageProcessorCore/Formats/Gif/GifDecoderCore.cs
index fbd421ccf..a587a7df3 100644
--- a/src/ImageProcessorCore/Formats/Gif/GifDecoderCore.cs
+++ b/src/ImageProcessorCore/Formats/Gif/GifDecoderCore.cs
@@ -12,7 +12,7 @@ namespace ImageProcessorCore.Formats
/// Performs the gif decoding operation.
///
/// The pixel format.
- /// The packed format. uint, long, float.
+ /// The packed format. uint, long, float.
internal class GifDecoderCore
where TColor : IPackedVector
where TPacked : struct
diff --git a/src/ImageProcessorCore/Formats/Gif/LzwDecoder.cs b/src/ImageProcessorCore/Formats/Gif/LzwDecoder.cs
index 1474cc708..7135ca62e 100644
--- a/src/ImageProcessorCore/Formats/Gif/LzwDecoder.cs
+++ b/src/ImageProcessorCore/Formats/Gif/LzwDecoder.cs
@@ -5,7 +5,6 @@
namespace ImageProcessorCore.Formats
{
- using System;
using System.IO;
///
diff --git a/src/ImageProcessorCore/Formats/Gif/LzwEncoder.cs b/src/ImageProcessorCore/Formats/Gif/LzwEncoder.cs
index 469cacbce..a9681d2c5 100644
--- a/src/ImageProcessorCore/Formats/Gif/LzwEncoder.cs
+++ b/src/ImageProcessorCore/Formats/Gif/LzwEncoder.cs
@@ -310,7 +310,7 @@ namespace ImageProcessorCore.Formats
}
///
- /// Return the nexTColor pixel from the image
+ /// Return the next pixel from the image
///
///
/// The
diff --git a/src/ImageProcessorCore/Formats/Gif/Sections/GifGraphicsControlExtension.cs b/src/ImageProcessorCore/Formats/Gif/Sections/GifGraphicsControlExtension.cs
index 59dbceb21..071dc62c8 100644
--- a/src/ImageProcessorCore/Formats/Gif/Sections/GifGraphicsControlExtension.cs
+++ b/src/ImageProcessorCore/Formats/Gif/Sections/GifGraphicsControlExtension.cs
@@ -27,7 +27,7 @@ namespace ImageProcessorCore.Formats
///
/// Gets or sets the transparency index.
/// The Transparency Index is such that when encountered, the corresponding pixel
- /// of the display device is not modified and processing goes on to the nexTColor pixel.
+ /// of the display device is not modified and processing goes on to the next pixel.
///
public int TransparencyIndex { get; set; }
diff --git a/src/ImageProcessorCore/Formats/IImageEncoder.cs b/src/ImageProcessorCore/Formats/IImageEncoder.cs
index 808371456..445b7f645 100644
--- a/src/ImageProcessorCore/Formats/IImageEncoder.cs
+++ b/src/ImageProcessorCore/Formats/IImageEncoder.cs
@@ -38,11 +38,11 @@ namespace ImageProcessorCore.Formats
bool IsSupportedFileExtension(string extension);
///
- /// Encodes the image to the specified stream from the .
+ /// Encodes the image to the specified stream from the .
///
/// The pixel format.
/// The packed format. uint, long, float.
- /// The to encode from.
+ /// The to encode from.
/// The to encode the image data to.
void Encode(Image image, Stream stream)
where TColor : IPackedVector
diff --git a/src/ImageProcessorCore/Formats/Jpg/JpegDecoderCore.cs.REMOVED.git-id b/src/ImageProcessorCore/Formats/Jpg/JpegDecoderCore.cs.REMOVED.git-id
index 45afa1afc..1f1ad448b 100644
--- a/src/ImageProcessorCore/Formats/Jpg/JpegDecoderCore.cs.REMOVED.git-id
+++ b/src/ImageProcessorCore/Formats/Jpg/JpegDecoderCore.cs.REMOVED.git-id
@@ -1 +1 @@
-508fcf1910c42f4e080fcfd9c9f22ba724c1990c
\ No newline at end of file
+c27ddeac481f3a9631dcb53248a98676c8016f42
\ No newline at end of file
diff --git a/src/ImageProcessorCore/Formats/Jpg/JpegEncoderCore.cs b/src/ImageProcessorCore/Formats/Jpg/JpegEncoderCore.cs
index baab490cf..57ab79181 100644
--- a/src/ImageProcessorCore/Formats/Jpg/JpegEncoderCore.cs
+++ b/src/ImageProcessorCore/Formats/Jpg/JpegEncoderCore.cs
@@ -504,7 +504,7 @@ namespace ImageProcessorCore.Formats
// Write the image data.
using (PixelAccessor pixels = image.Lock())
{
- this.WriteSOS(pixels);
+ this.WriteSOS(pixels);
}
// Write the End Of Image marker.
@@ -720,10 +720,10 @@ namespace ImageProcessorCore.Formats
switch (this.subsample)
{
case JpegSubsample.Ratio444:
- this.Encode444(pixels);
+ this.Encode444(pixels);
break;
case JpegSubsample.Ratio420:
- this.Encode420(pixels);
+ this.Encode420(pixels);
break;
}
@@ -750,7 +750,7 @@ namespace ImageProcessorCore.Formats
{
for (int x = 0; x < pixels.Width; x += 8)
{
- this.ToYCbCr(pixels, x, y, b, cb, cr);
+ this.ToYCbCr(pixels, x, y, b, cb, cr);
prevDCY = this.WriteBlock(b, QuantIndex.Luminance, prevDCY);
prevDCCb = this.WriteBlock(cb, QuantIndex.Chrominance, prevDCCb);
prevDCCr = this.WriteBlock(cr, QuantIndex.Chrominance, prevDCCr);
@@ -784,7 +784,7 @@ namespace ImageProcessorCore.Formats
int xOff = (i & 1) * 8;
int yOff = (i & 2) * 4;
- this.ToYCbCr(pixels, x + xOff, y + yOff, b, cb[i], cr[i]);
+ this.ToYCbCr(pixels, x + xOff, y + yOff, b, cb[i], cr[i]);
prevDCY = this.WriteBlock(b, QuantIndex.Luminance, prevDCY);
}
diff --git a/src/ImageProcessorCore/Formats/Png/Filters/UpFilter.cs b/src/ImageProcessorCore/Formats/Png/Filters/UpFilter.cs
index deb4d9d0d..8f87ec1ca 100644
--- a/src/ImageProcessorCore/Formats/Png/Filters/UpFilter.cs
+++ b/src/ImageProcessorCore/Formats/Png/Filters/UpFilter.cs
@@ -6,7 +6,7 @@
namespace ImageProcessorCore.Formats
{
///
- /// The Up filter is just like the Sub filter except that the pixel immediately above the currenTColor pixel,
+ /// The Up filter is just like the Sub filter except that the pixel immediately above the current pixel,
/// rather than just to its left, is used as the predictor.
///
///
diff --git a/src/ImageProcessorCore/Formats/Png/PngDecoder.cs b/src/ImageProcessorCore/Formats/Png/PngDecoder.cs
index 264971e4d..0fad54dd7 100644
--- a/src/ImageProcessorCore/Formats/Png/PngDecoder.cs
+++ b/src/ImageProcessorCore/Formats/Png/PngDecoder.cs
@@ -77,6 +77,8 @@ namespace ImageProcessorCore.Formats
///
/// Decodes the image from the specified stream to the .
///
+ /// The pixel format.
+ /// The packed format. uint, long, float.
/// The to decode to.
/// The containing image data.
public void Decode(Image image, Stream stream)
diff --git a/src/ImageProcessorCore/Formats/Png/PngDecoderCore.cs b/src/ImageProcessorCore/Formats/Png/PngDecoderCore.cs
index f9cc691cb..c449b72d9 100644
--- a/src/ImageProcessorCore/Formats/Png/PngDecoderCore.cs
+++ b/src/ImageProcessorCore/Formats/Png/PngDecoderCore.cs
@@ -83,13 +83,13 @@ namespace ImageProcessorCore.Formats
/// Decodes the stream to the image.
///
/// The pixel format.
- /// The packed format. uint, long, float.
+ /// The packed format. uint, long, float.
/// The image to decode to.
/// The stream containing image data.
///
/// Thrown if the stream does not contain and end chunk.
///
- ///
+ ///
/// Thrown if the image is larger than the maximum allowable size.
///
public void Decode(Image image, Stream stream)
@@ -152,11 +152,7 @@ namespace ImageProcessorCore.Formats
}
TColor[] pixels = new TColor[this.header.Width * this.header.Height];
-
-
this.ReadScanlines(dataStream, pixels);
-
-
image.SetPixels(this.header.Width, this.header.Height, pixels);
}
}
@@ -228,9 +224,10 @@ namespace ImageProcessorCore.Formats
///
/// Reads the scanlines within the image.
///
+ /// The pixel format.
+ /// The packed format. uint, long, float.
/// The containing data.
- ///
- /// The containing pixel data.
+ /// The pixel data.
private void ReadScanlines(MemoryStream dataStream, TColor[] pixels)
where TColor : IPackedVector
where TPacked : struct
diff --git a/src/ImageProcessorCore/Formats/Png/PngEncoder.cs b/src/ImageProcessorCore/Formats/Png/PngEncoder.cs
index 660315c58..75f686857 100644
--- a/src/ImageProcessorCore/Formats/Png/PngEncoder.cs
+++ b/src/ImageProcessorCore/Formats/Png/PngEncoder.cs
@@ -73,8 +73,8 @@ namespace ImageProcessorCore.Formats
///
public void Encode(Image image, Stream stream)
- where TColor : IPackedVector
- where TPacked : struct
+ where TColor : IPackedVector
+ where TPacked : struct
{
PngEncoderCore encoder = new PngEncoderCore
{
diff --git a/src/ImageProcessorCore/IO/EndianBitConverter.cs b/src/ImageProcessorCore/IO/EndianBitConverter.cs
index 71cba1a51..107148100 100644
--- a/src/ImageProcessorCore/IO/EndianBitConverter.cs
+++ b/src/ImageProcessorCore/IO/EndianBitConverter.cs
@@ -246,7 +246,7 @@ namespace ImageProcessorCore.IO
/// The start index passed in
/// The number of bytes required
/// value is a null reference
- ///
+ ///
/// startIndex is less than zero or greater than the length of value minus bytesRequired.
///
[SuppressMessage("ReSharper", "UnusedParameter.Local", Justification = "Keeps code DRY")]
diff --git a/src/ImageProcessorCore/Image/IImageBase.cs b/src/ImageProcessorCore/Image/IImageBase.cs
index 1afd7daaf..cc2ef9a79 100644
--- a/src/ImageProcessorCore/Image/IImageBase.cs
+++ b/src/ImageProcessorCore/Image/IImageBase.cs
@@ -5,8 +5,6 @@
namespace ImageProcessorCore
{
- using System;
-
///
/// Encapsulates the basic properties and methods required to manipulate images in varying formats.
///
@@ -27,10 +25,10 @@ namespace ImageProcessorCore
/// The new width of the image. Must be greater than zero.
/// The new height of the image. Must be greater than zero.
/// The array with pixels. Must be a multiple of the width and height.
- ///
+ ///
/// Thrown if either or are less than or equal to 0.
///
- ///
+ ///
/// Thrown if the length is not equal to Width * Height.
///
void SetPixels(int width, int height, TColor[] pixels);
@@ -42,10 +40,10 @@ namespace ImageProcessorCore
/// The new width of the image. Must be greater than zero.
/// The new height of the image. Must be greater than zero.
/// The array with pixels. Must be a multiple of four times the width and height.
- ///
+ ///
/// Thrown if either or are less than or equal to 0.
///
- ///
+ ///
/// Thrown if the length is not equal to Width * Height.
///
void ClonePixels(int width, int height, TColor[] pixels);
@@ -56,7 +54,7 @@ namespace ImageProcessorCore
/// It is imperative that the accessor is correctly disposed off after use.
///
///
- /// The
+ /// The
PixelAccessor Lock();
}
diff --git a/src/ImageProcessorCore/Image/IImageProcessor.cs b/src/ImageProcessorCore/Image/IImageProcessor.cs
index cf9f2c15d..06f0514d8 100644
--- a/src/ImageProcessorCore/Image/IImageProcessor.cs
+++ b/src/ImageProcessorCore/Image/IImageProcessor.cs
@@ -44,7 +44,7 @@ namespace ImageProcessorCore.Processors
bool Compand { get; set; }
///
- /// Applies the process to the specified portion of the specified .
+ /// Applies the process to the specified portion of the specified .
///
/// Target image to apply the process to.
/// The source image. Cannot be null.
@@ -64,7 +64,7 @@ namespace ImageProcessorCore.Processors
void Apply(ImageBase target, ImageBase source, Rectangle sourceRectangle);
///
- /// Applies the process to the specified portion of the specified at the specified
+ /// Applies the process to the specified portion of the specified at the specified
/// location and with the specified size.
///
/// Target image to apply the process to.
diff --git a/src/ImageProcessorCore/Image/ImageBase.cs b/src/ImageProcessorCore/Image/ImageBase.cs
index 9f4b36323..4d17d9f01 100644
--- a/src/ImageProcessorCore/Image/ImageBase.cs
+++ b/src/ImageProcessorCore/Image/ImageBase.cs
@@ -3,8 +3,6 @@
// Licensed under the Apache License, Version 2.0.
//
-using System.Runtime.CompilerServices;
-
namespace ImageProcessorCore
{
using System;
@@ -12,20 +10,15 @@ namespace ImageProcessorCore
///
/// The base class of all images. Encapsulates the basic properties and methods required to manipulate
- /// images in differenTColor pixel formats.
+ /// images in different pixel formats.
///
/// The pixel format.
/// The packed format. uint, long, float.
[DebuggerDisplay("Image: {Width}x{Height}")]
- public abstract unsafe class ImageBase : IImageBase
+ public abstract class ImageBase : IImageBase
where TColor : IPackedVector
where TPacked : struct
{
- ///
- /// The image pixels
- ///
- private TColor[] pixelBuffer;
-
///
/// Initializes a new instance of the class.
///
@@ -38,7 +31,7 @@ namespace ImageProcessorCore
///
/// The width of the image in pixels.
/// The height of the image in pixels.
- ///
+ ///
/// Thrown if either or are less than or equal to 0.
///
protected ImageBase(int width, int height)
@@ -48,7 +41,7 @@ namespace ImageProcessorCore
this.Width = width;
this.Height = height;
- this.pixelBuffer = new TColor[width * height];
+ this.Pixels = new TColor[width * height];
}
///
@@ -68,9 +61,9 @@ namespace ImageProcessorCore
this.Height = other.Height;
this.CopyProperties(other);
- // Copy the pixels.
- this.pixelBuffer = new TColor[this.Width * this.Height];
- Unsafe.Copy(Unsafe.AsPointer(ref this.pixelBuffer), ref other.pixelBuffer);
+ // Copy the pixels. Don't use Unsafe.Copy as it is breaking edge detection.
+ this.Pixels = new TColor[this.Width * this.Height];
+ Array.Copy(other.Pixels, this.Pixels, other.Pixels.Length);
}
///
@@ -80,7 +73,7 @@ namespace ImageProcessorCore
public int MaxHeight { get; set; } = int.MaxValue;
///
- public TColor[] Pixels => this.pixelBuffer;
+ public TColor[] Pixels { get; private set; }
///
public int Width { get; private set; }
@@ -103,15 +96,8 @@ namespace ImageProcessorCore
///
public void SetPixels(int width, int height, TColor[] pixels)
{
- if (width <= 0)
- {
- throw new ArgumentOutOfRangeException(nameof(width), "Width must be greater than or equals than zero.");
- }
-
- if (height <= 0)
- {
- throw new ArgumentOutOfRangeException(nameof(height), "Height must be greater than or equal than zero.");
- }
+ Guard.MustBeGreaterThan(width, 0, nameof(width));
+ Guard.MustBeGreaterThan(height, 0, nameof(height));
if (pixels.Length != width * height)
{
@@ -120,21 +106,14 @@ namespace ImageProcessorCore
this.Width = width;
this.Height = height;
- this.pixelBuffer = pixels;
+ this.Pixels = pixels;
}
///
public void ClonePixels(int width, int height, TColor[] pixels)
{
- if (width <= 0)
- {
- throw new ArgumentOutOfRangeException(nameof(width), "Width must be greater than or equals than zero.");
- }
-
- if (height <= 0)
- {
- throw new ArgumentOutOfRangeException(nameof(height), "Height must be greater than or equal than zero.");
- }
+ Guard.MustBeGreaterThan(width, 0, nameof(width));
+ Guard.MustBeGreaterThan(height, 0, nameof(height));
if (pixels.Length != width * height)
{
@@ -144,9 +123,9 @@ namespace ImageProcessorCore
this.Width = width;
this.Height = height;
- // Copy the pixels.
- this.pixelBuffer = new TColor[pixels.Length];
- Unsafe.Copy(Unsafe.AsPointer(ref this.pixelBuffer), ref pixels);
+ // Copy the pixels. Don't use Unsafe.Copy as it is breaking edge detection.
+ this.Pixels = new TColor[pixels.Length];
+ Array.Copy(pixels, this.Pixels, pixels.Length);
}
///
diff --git a/src/ImageProcessorCore/Image/ImageExtensions.cs b/src/ImageProcessorCore/Image/ImageExtensions.cs
index 476c2a48e..103f8c3eb 100644
--- a/src/ImageProcessorCore/Image/ImageExtensions.cs
+++ b/src/ImageProcessorCore/Image/ImageExtensions.cs
@@ -20,7 +20,7 @@ namespace ImageProcessorCore
/// Saves the image to the given stream with the bmp format.
///
/// The pixel format.
- /// The packed format. uint, long, float.
+ /// The packed format. uint, long, float.
/// The image this method extends.
/// The stream to save the image to.
/// Thrown if the stream is null.
@@ -34,7 +34,7 @@ namespace ImageProcessorCore
/// Saves the image to the given stream with the png format.
///
/// The pixel format.
- /// The packed format. uint, long, float.
+ /// The packed format. uint, long, float.
/// The image this method extends.
/// The stream to save the image to.
/// The quality to save the image to representing the number of colors.
@@ -50,7 +50,7 @@ namespace ImageProcessorCore
/// Saves the image to the given stream with the jpeg format.
///
/// The pixel format.
- /// The packed format. uint, long, float.
+ /// The packed format. uint, long, float.
/// The image this method extends.
/// The stream to save the image to.
/// The quality to save the image to. Between 1 and 100.
@@ -64,7 +64,7 @@ namespace ImageProcessorCore
/// Saves the image to the given stream with the gif format.
///
/// The pixel format.
- /// The packed format. uint, long, float.
+ /// The packed format. uint, long, float.
/// The image this method extends.
/// The stream to save the image to.
/// The quality to save the image to representing the number of colors. Between 1 and 256.
@@ -115,8 +115,8 @@ namespace ImageProcessorCore
/// This method is not chainable.
///
///
- /// The pixel format.
- /// The packed format. uint, long, float.
+ /// The pixel format.
+ /// The packed format. long, float.
/// The source image. Cannot be null.
/// The target image width.
/// The target image height.
@@ -135,8 +135,8 @@ namespace ImageProcessorCore
/// This method does will resize the target image if the source and target rectangles are different.
///
///
- /// The pixel format.
- /// The packed format. uint, long, float.
+ /// The pixel format.
+ /// The packed format. long, float.
/// The source image. Cannot be null.
/// The target image width.
/// The target image height.
@@ -159,8 +159,8 @@ namespace ImageProcessorCore
///
/// Performs the given action on the source image.
///
- /// The pixel format.
- /// The packed format. uint, long, float.
+ /// The pixel format.
+ /// The packed format. long, float.
/// The image to perform the action against.
/// Whether to clone the image.
/// The to perform against the image.
diff --git a/src/ImageProcessorCore/Image/PixelAccessor.cs b/src/ImageProcessorCore/Image/PixelAccessor.cs
index 343b60dd1..8ebfb355e 100644
--- a/src/ImageProcessorCore/Image/PixelAccessor.cs
+++ b/src/ImageProcessorCore/Image/PixelAccessor.cs
@@ -14,7 +14,7 @@ namespace ImageProcessorCore
///
/// The pixel format.
/// The packed format. uint, long, float.
- public sealed unsafe class PixelAccessor : IDisposable
+ public unsafe class PixelAccessor : IDisposable
where TColor : IPackedVector
where TPacked : struct
{
@@ -104,8 +104,28 @@ namespace ImageProcessorCore
/// The at the specified position.
public TColor this[int x, int y]
{
- get { return Unsafe.Read(pixelsBase + ((y * this.RowStride) + (x * this.PixelSize))); }
- set { Unsafe.Write(pixelsBase + ((y * this.RowStride) + (x * this.PixelSize)), value); }
+ get { return Unsafe.Read(this.pixelsBase + (y * this.Width + x) * Unsafe.SizeOf()); }
+ set { Unsafe.Write(this.pixelsBase + (y * this.Width + x) * Unsafe.SizeOf(), value); }
+
+ }
+
+ ///
+ /// Copies an entire row of pixels.
+ ///
+ /// The x-coordinate of the source row.
+ /// The y-coordinate of the source row.
+ /// The target pixel buffer accessor.
+ /// The x-coordinate of the target row.
+ /// The y-coordinate of the target row.
+ /// The number of pixels to copy
+ public void CopyRow(int sourceX, int sourceY, PixelAccessor target, int targetX, int targetY, int pixelCount)
+ {
+ int size = Unsafe.SizeOf();
+ byte* sourcePtr = this.pixelsBase + (sourceY * this.Width + sourceX) * size;
+ byte* targetPtr = target.pixelsBase + (targetY * target.Width + targetX) * size;
+ uint byteCount = (uint)(pixelCount * size);
+
+ Unsafe.CopyBlock(targetPtr, sourcePtr, byteCount);
}
///
diff --git a/src/ImageProcessorCore/ImageProcessor.cs b/src/ImageProcessorCore/ImageProcessor.cs
index 2ed0e56b2..10014e0f3 100644
--- a/src/ImageProcessorCore/ImageProcessor.cs
+++ b/src/ImageProcessorCore/ImageProcessor.cs
@@ -12,6 +12,8 @@ namespace ImageProcessorCore.Processors
///
/// Allows the application of processors to images.
///
+ /// The pixel format.
+ /// The packed format. uint, long, float.
public abstract class ImageProcessor : IImageProcessor
where TColor : IPackedVector
where TPacked : struct
@@ -93,8 +95,6 @@ namespace ImageProcessorCore.Processors
///
/// This method is called before the process is applied to prepare the processor.
///
- /// The pixel format.
- /// The packed format. uint, long, float.
/// Target image to apply the process to.
/// The source image. Cannot be null.
///
diff --git a/src/ImageProcessorCore/Numerics/BigRational.cs b/src/ImageProcessorCore/Numerics/BigRational.cs
new file mode 100644
index 000000000..965979674
--- /dev/null
+++ b/src/ImageProcessorCore/Numerics/BigRational.cs
@@ -0,0 +1,219 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageProcessorCore
+{
+ using System;
+ using System.Text;
+
+ internal struct BigRational : IEquatable
+ {
+ private bool IsIndeterminate
+ {
+ get
+ {
+ if (Denominator != 0)
+ return false;
+
+ return Numerator == 0;
+ }
+ }
+
+ private bool IsInteger => Denominator == 1;
+
+ private bool IsNegativeInfinity
+ {
+ get
+ {
+ if (Denominator != 0)
+ return false;
+
+ return Numerator == -1;
+ }
+ }
+
+ private bool IsPositiveInfinity
+ {
+ get
+ {
+ if (Denominator != 0)
+ return false;
+
+ return Numerator == 1;
+ }
+ }
+
+ private bool IsZero
+ {
+ get
+ {
+ if (Denominator != 1)
+ return false;
+
+ return Numerator == 0;
+ }
+ }
+
+ private static long GreatestCommonDivisor(long a, long b)
+ {
+ return b == 0 ? a : GreatestCommonDivisor(b, a % b);
+ }
+
+ private void Simplify()
+ {
+ if (IsIndeterminate)
+ return;
+
+ if (IsNegativeInfinity)
+ return;
+
+ if (IsPositiveInfinity)
+ return;
+
+ if (IsInteger)
+ return;
+
+ if (IsZero)
+ return;
+
+ if (Numerator == 0)
+ {
+ Denominator = 0;
+ return;
+ }
+
+ if (Numerator == Denominator)
+ {
+ Numerator = 1;
+ Denominator = 1;
+ }
+
+ long gcd = GreatestCommonDivisor(Math.Abs(Numerator), Math.Abs(Denominator));
+ if (gcd > 1)
+ {
+ Numerator = Numerator / gcd;
+ Denominator = Denominator / gcd;
+ }
+ }
+
+ public BigRational(long numerator, long denominator)
+ : this(numerator, denominator, false)
+ {
+ }
+
+ public BigRational(long numerator, long denominator, bool simplify)
+ {
+ Numerator = numerator;
+ Denominator = denominator;
+
+ if (simplify)
+ Simplify();
+ }
+
+ public BigRational(double value, bool bestPrecision)
+ {
+ if (double.IsNaN(value))
+ {
+ Numerator = Denominator = 0;
+ return;
+ }
+
+ if (double.IsPositiveInfinity(value))
+ {
+ Numerator = 1;
+ Denominator = 0;
+ return;
+ }
+
+ if (double.IsNegativeInfinity(value))
+ {
+ Numerator = -1;
+ Denominator = 0;
+ return;
+ }
+
+ Numerator = 1;
+ Denominator = 1;
+
+ double val = Math.Abs(value);
+ double df = Numerator / Denominator;
+ double epsilon = bestPrecision ? double.Epsilon : .000001;
+
+ while (Math.Abs(df - val) > epsilon)
+ {
+ if (df < val)
+ Numerator++;
+ else
+ {
+ Denominator++;
+ Numerator = (int)(val * Denominator);
+ }
+
+ df = Numerator / (double)Denominator;
+ }
+
+ if (value < 0.0)
+ Numerator *= -1;
+
+ Simplify();
+ }
+
+ public long Denominator
+ {
+ get;
+ private set;
+ }
+
+ public long Numerator
+ {
+ get;
+ private set;
+ }
+
+ public bool Equals(BigRational other)
+ {
+ if (Denominator == other.Denominator)
+ return Numerator == other.Numerator;
+
+ if (Numerator == 0 && Denominator == 0)
+ return other.Numerator == 0 && other.Denominator == 0;
+
+ if (other.Numerator == 0 && other.Denominator == 0)
+ return Numerator == 0 && Denominator == 0;
+
+ return (Numerator * other.Denominator) == (Denominator * other.Numerator);
+ }
+
+ public override int GetHashCode()
+ {
+ return ((Numerator * 397) ^ Denominator).GetHashCode();
+ }
+
+ public string ToString(IFormatProvider provider)
+ {
+ if (IsIndeterminate)
+ return "[ Indeterminate ]";
+
+ if (IsPositiveInfinity)
+ return "[ PositiveInfinity ]";
+
+ if (IsNegativeInfinity)
+ return "[ NegativeInfinity ]";
+
+ if (IsZero)
+ return "0";
+
+ if (IsInteger)
+ return Numerator.ToString(provider);
+
+ StringBuilder sb = new StringBuilder();
+ sb.Append(Numerator.ToString(provider));
+ sb.Append("/");
+ sb.Append(Denominator.ToString(provider));
+
+ return sb.ToString();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageProcessorCore/Numerics/Rational.cs b/src/ImageProcessorCore/Numerics/Rational.cs
index 090af6e3c..1de71fa86 100644
--- a/src/ImageProcessorCore/Numerics/Rational.cs
+++ b/src/ImageProcessorCore/Numerics/Rational.cs
@@ -7,11 +7,9 @@ namespace ImageProcessorCore
{
using System;
using System.Globalization;
- using System.Numerics;
- using System.Text;
///
- /// Represents a number that can be expressed as a fraction
+ /// Represents a number that can be expressed as a fraction.
///
///
/// This is a very simplified implimentation of a rational number designed for use with metadata only.
@@ -19,532 +17,183 @@ namespace ImageProcessorCore
public struct Rational : IEquatable
{
///
- /// Represents a rational object that is not a number; NaN (0, 0)
+ /// Initializes a new instance of the struct.
///
- public static Rational Indeterminate = new Rational(BigInteger.Zero);
-
- ///
- /// Represents a rational object that is equal to 0 (0, 1)
- ///
- public static Rational Zero = new Rational(BigInteger.Zero);
-
- ///
- /// Represents a rational object that is equal to 1 (1, 1)
- ///
- public static Rational One = new Rational(BigInteger.One);
-
- ///
- /// Represents a Rational object that is equal to negative infinity (-1, 0)
- ///
- public static readonly Rational NegativeInfinity = new Rational(BigInteger.MinusOne, BigInteger.Zero);
-
- ///
- /// Represents a Rational object that is equal to positive infinity (1, 0)
- ///
- public static readonly Rational PositiveInfinity = new Rational(BigInteger.One, BigInteger.Zero);
-
- ///
- /// The maximum number of decimal places
- ///
- private const int DoubleMaxScale = 308;
-
- ///
- /// The maximum precision (numbers after the decimal point)
- ///
- private static readonly BigInteger DoublePrecision = BigInteger.Pow(10, DoubleMaxScale);
-
- ///
- /// Represents double.MaxValue
- ///
- private static readonly BigInteger DoubleMaxValue = (BigInteger)double.MaxValue;
-
- ///
- /// Represents double.MinValue
- ///
- private static readonly BigInteger DoubleMinValue = (BigInteger)double.MinValue;
-
- ///
- /// Initializes a new instance of the struct.
- ///
- ///
- /// The number above the line in a vulgar fraction showing how many of the parts
- /// indicated by the denominator are taken.
- ///
- ///
- /// The number below the line in a vulgar fraction; a divisor.
- ///
- public Rational(uint numerator, uint denominator)
- : this()
- {
- this.Numerator = numerator;
- this.Denominator = denominator;
-
- this.Simplify();
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- ///
- /// The number above the line in a vulgar fraction showing how many of the parts
- /// indicated by the denominator are taken.
- ///
- ///
- /// The number below the line in a vulgar fraction; a divisor.
- ///
- public Rational(int numerator, int denominator)
- : this()
+ ///The to convert to an instance of this type.
+ public Rational(double value)
+ : this(value, false)
{
- this.Numerator = numerator;
- this.Denominator = denominator;
-
- this.Simplify();
}
///
- /// Initializes a new instance of the struct.
+ /// Initializes a new instance of the struct.
///
- ///
- /// The number above the line in a vulgar fraction showing how many of the parts
- /// indicated by the denominator are taken.
- ///
- ///
- /// The number below the line in a vulgar fraction; a divisor.
- ///
- public Rational(BigInteger numerator, BigInteger denominator)
- : this()
+ ///The to convert to an instance of this type.
+ ///Specifies if the instance should be created with the best precision possible.
+ public Rational(double value, bool bestPrecision)
{
- this.Numerator = numerator;
- this.Denominator = denominator;
+ BigRational rational = new BigRational(Math.Abs(value), bestPrecision);
- this.Simplify();
+ Numerator = (uint)rational.Numerator;
+ Denominator = (uint)rational.Denominator;
}
///
- /// Initializes a new instance of the struct.
+ /// Initializes a new instance of the struct.
///
- /// The big integer to create the rational from.
- public Rational(BigInteger value)
- : this()
+ /// The integer to create the rational from.
+ public Rational(uint value)
+ : this(value, 1)
{
- this.Numerator = value;
- this.Denominator = BigInteger.One;
-
- this.Simplify();
}
///
- /// Initializes a new instance of the struct.
+ /// Initializes a new instance of the struct.
///
- /// The double to create the rational from.
- public Rational(double value)
- : this()
- {
- if (double.IsNaN(value))
- {
- this = Indeterminate;
- return;
- }
-
- if (double.IsPositiveInfinity(value))
- {
- this = PositiveInfinity;
- return;
- }
-
- if (double.IsNegativeInfinity(value))
- {
- this = NegativeInfinity;
- return;
- }
-
- // TODO: Not happy with parsing a string like this. I should be able to use maths but maths is HARD!
- this = Parse(value.ToString("R", CultureInfo.InvariantCulture));
- }
-
- ///
- /// Gets the numerator of a number.
- ///
- public BigInteger Numerator { get; private set; }
-
- ///
- /// Gets the denominator of a number.
- ///
- public BigInteger Denominator { get; private set; }
-
- ///
- /// Gets a value indicating whether this instance is indeterminate.
- ///
- public bool IsIndeterminate
+ /// The number above the line in a vulgar fraction showing how many of the parts indicated by the denominator are taken.
+ /// The number below the line in a vulgar fraction; a divisor.
+ public Rational(uint numerator, uint denominator)
+ : this(numerator, denominator, true)
{
- get
- {
- if (this.Denominator != BigInteger.Zero)
- {
- return false;
- }
-
- return this.Numerator == BigInteger.Zero;
- }
}
///
- /// Gets a value indicating whether this instance is an integer (n, 1)
+ /// Initializes a new instance of the struct.
///
- public bool IsInteger => this.Denominator == BigInteger.One;
-
- ///
- /// Gets a value indicating whether this instance is equal to 0 (0, 1)
- ///
- public bool IsZero
+ /// The number above the line in a vulgar fraction showing how many of the parts indicated by the denominator are taken.
+ /// The number below the line in a vulgar fraction; a divisor.
+ /// Specified if the rational should be simplified.
+ public Rational(uint numerator, uint denominator, bool simplify)
{
- get
- {
- if (this.Denominator != BigInteger.One)
- {
- return false;
- }
+ BigRational rational = new BigRational(numerator, denominator, simplify);
- return this.Numerator == BigInteger.Zero;
- }
+ Numerator = (uint)rational.Numerator;
+ Denominator = (uint)rational.Denominator;
}
///
- /// Gets a value indicating whether this instance is equal to 1 (1, 1)
+ /// Determines whether the specified instances are considered equal.
///
- public bool IsOne
+ /// The first to compare.
+ /// The second to compare.
+ ///
+ public static bool operator ==(Rational left, Rational right)
{
- get
- {
- if (this.Denominator != BigInteger.One)
- {
- return false;
- }
-
- return this.Numerator == BigInteger.One;
- }
+ return Equals(left, right);
}
///
- /// Gets a value indicating whether this instance is equal to negative infinity (-1, 0)
+ /// Determines whether the specified instances are not considered equal.
///
- public bool IsNegativeInfinity
+ /// The first to compare.
+ /// The second to compare.
+ ///
+ public static bool operator !=(Rational left, Rational right)
{
- get
- {
- if (this.Denominator != BigInteger.Zero)
- {
- return false;
- }
-
- return this.Numerator == BigInteger.MinusOne;
- }
+ return !Equals(left, right);
}
///
- /// Gets a value indicating whether this instance is equal to positive infinity (1, 0)
+ /// Gets the numerator of a number.
///
- public bool IsPositiveInfinity
+ public uint Numerator
{
- get
- {
- if (this.Denominator != BigInteger.Zero)
- {
- return false;
- }
-
- return this.Numerator == BigInteger.One;
- }
+ get;
+ private set;
}
///
- /// Converts a rational number to the nearest double.
+ /// Gets the denominator of a number.
///
- ///
- /// The .
- ///
- public double ToDouble()
+ public uint Denominator
{
- // Shortcut return values
- if (this.IsIndeterminate)
- {
- return double.NaN;
- }
-
- if (this.IsPositiveInfinity)
- {
- return double.PositiveInfinity;
- }
-
- if (this.IsNegativeInfinity)
- {
- return double.NegativeInfinity;
- }
-
- if (this.IsInteger)
- {
- return (double)this.Numerator;
- }
-
- // The Double value type represents a double-precision 64-bit number with
- // values ranging from -1.79769313486232e308 to +1.79769313486232e308
- // values that do not fit into this range are returned as +/-Infinity
- if (SafeCastToDouble(this.Numerator) && SafeCastToDouble(this.Denominator))
- {
- return (double)this.Numerator / (double)this.Denominator;
- }
-
- // Scale the numerator to preserve the fraction part through the integer division
- // We could probably adjust this to make it less precise if need be.
- BigInteger denormalized = (this.Numerator * DoublePrecision) / this.Denominator;
- if (denormalized.IsZero)
- {
- // underflow to -+0
- return (this.Numerator.Sign < 0) ? BitConverter.Int64BitsToDouble(unchecked((long)0x8000000000000000)) : 0d;
- }
-
- double result = 0;
- bool isDouble = false;
- int scale = DoubleMaxScale;
-
- while (scale > 0)
- {
- if (!isDouble)
- {
- if (SafeCastToDouble(denormalized))
- {
- result = (double)denormalized;
- isDouble = true;
- }
- else
- {
- denormalized = denormalized / 10;
- }
- }
-
- result = result / 10;
- scale--;
- }
-
- if (!isDouble)
- {
- return (this.Numerator.Sign < 0) ? double.NegativeInfinity : double.PositiveInfinity;
- }
- else
- {
- return result;
- }
+ get;
+ private set;
}
- ///
+ ///
+ /// Determines whether the specified is equal to this .
+ ///
+ ///The to compare this with.
public override bool Equals(object obj)
{
if (obj is Rational)
- {
- return this.Equals((Rational)obj);
- }
+ return Equals((Rational)obj);
return false;
}
- ///
+ ///
+ /// Determines whether the specified is equal to this .
+ ///
+ ///The to compare this with.
public bool Equals(Rational other)
{
- // Standard: a/b = c/d
- if (this.Denominator == other.Denominator)
- {
- return this.Numerator == other.Numerator;
- }
-
- // Indeterminate
- if (this.Numerator == BigInteger.Zero && this.Denominator == BigInteger.Zero)
- {
- return other.Numerator == BigInteger.Zero && other.Denominator == BigInteger.Zero;
- }
-
- if (other.Numerator == BigInteger.Zero && other.Denominator == BigInteger.Zero)
- {
- return this.Numerator == BigInteger.Zero && this.Denominator == BigInteger.Zero;
- }
+ BigRational left = new BigRational(Numerator, Denominator);
+ BigRational right = new BigRational(other.Numerator, other.Denominator);
- // ad = bc
- return (this.Numerator * other.Denominator) == (this.Denominator * other.Numerator);
- }
-
- ///
- public override int GetHashCode()
- {
- return this.GetHashCode(this);
+ return left.Equals(right);
}
- ///
- public override string ToString()
+ ///
+ /// Converts the specified to an instance of this type.
+ ///
+ ///The to convert to an instance of this type.
+ public static Rational FromDouble(double value)
{
- return this.ToString(CultureInfo.InvariantCulture);
+ return new Rational(value, false);
}
- ///
- /// Converts the numeric value of this instance to its equivalent string representation using
- /// the specified culture-specific format information.
- ///
- ///
- /// An object that supplies culture-specific formatting information.
- ///
- ///
- public string ToString(IFormatProvider provider)
+ ///
+ /// Converts the specified to an instance of this type.
+ ///
+ ///The to convert to an instance of this type.
+ ///Specifies if the instance should be created with the best precision possible.
+ public static Rational FromDouble(double value, bool bestPrecision)
{
- if (this.IsIndeterminate)
- {
- return "[ Indeterminate ]";
- }
-
- if (this.IsPositiveInfinity)
- {
- return "[ PositiveInfinity ]";
- }
-
- if (this.IsNegativeInfinity)
- {
- return "[ NegativeInfinity ]";
- }
-
- if (this.IsZero)
- {
- return "0";
- }
-
- if (this.IsInteger)
- {
- return this.Numerator.ToString(provider);
- }
-
- StringBuilder sb = new StringBuilder();
- sb.Append(this.Numerator.ToString("R", provider));
- sb.Append("/");
- sb.Append(this.Denominator.ToString("R", provider));
- return sb.ToString();
+ return new Rational(value, bestPrecision);
}
- ///
- /// Simplifies the rational.
- ///
- private void Simplify()
+ ///
+ /// Serves as a hash of this type.
+ ///
+ public override int GetHashCode()
{
- if (this.IsIndeterminate)
- {
- return;
- }
-
- if (this.IsNegativeInfinity)
- {
- return;
- }
-
- if (this.IsPositiveInfinity)
- {
- return;
- }
-
- if (this.IsInteger)
- {
- return;
- }
-
- if (this.Numerator == BigInteger.Zero)
- {
- this.Denominator = BigInteger.One;
- return;
- }
-
- if (this.Numerator == this.Denominator)
- {
- this.Numerator = BigInteger.One;
- this.Denominator = BigInteger.One;
- return;
- }
-
- BigInteger gcd = BigInteger.GreatestCommonDivisor(this.Numerator, this.Denominator);
- if (gcd > BigInteger.One)
- {
- this.Numerator = this.Numerator / gcd;
- this.Denominator = this.Denominator / gcd;
- }
+ BigRational self = new BigRational(Numerator, Denominator);
+ return self.GetHashCode();
}
///
- /// Converts the string representation of a number into its rational value
+ /// Converts a rational number to the nearest .
///
- /// A string that contains a number to convert.
- /// The
- internal static Rational Parse(string value)
+ ///
+ /// The .
+ ///
+ public double ToDouble()
{
- int periodIndex = value.IndexOf(".", StringComparison.Ordinal);
- int eIndex = value.IndexOf("E", StringComparison.Ordinal);
- int slashIndex = value.IndexOf("/", StringComparison.Ordinal);
-
- // An integer such as 3
- if (periodIndex == -1 && eIndex == -1 && slashIndex == -1)
- {
- return new Rational(BigInteger.Parse(value));
- }
-
- // A fraction such as 22/7
- if (periodIndex == -1 && eIndex == -1 && slashIndex != -1)
- {
- return new Rational(BigInteger.Parse(value.Substring(0, slashIndex)),
- BigInteger.Parse(value.Substring(slashIndex + 1)));
- }
-
- // No scientific Notation such as 3.14159
- if (eIndex == -1)
- {
- BigInteger n = BigInteger.Parse(value.Replace(".", string.Empty));
- BigInteger d = (BigInteger)Math.Pow(10, value.Length - periodIndex - 1);
- return new Rational(n, d);
- }
-
- // Scientific notation such as 3.14159E-2
- int characteristic = int.Parse(value.Substring(eIndex + 1));
- BigInteger ten = 10;
- BigInteger numerator = BigInteger.Parse(value.Substring(0, eIndex).Replace(".", string.Empty));
- BigInteger denominator = new BigInteger(Math.Pow(10, eIndex - periodIndex - 1));
- BigInteger charPower = BigInteger.Pow(ten, Math.Abs(characteristic));
-
- if (characteristic > 0)
- {
- numerator = numerator * charPower;
- }
- else
- {
- denominator = denominator * charPower;
- }
-
- return new Rational(numerator, denominator);
+ return Numerator / (double)Denominator;
}
///
- /// Returns a value indicating whether the given big integer can be
- /// safely cast to a double.
+ /// Converts the numeric value of this instance to its equivalent string representation.
///
- /// The value to test.
- /// true if the value can be safely cast
- private static bool SafeCastToDouble(BigInteger value)
+ public override string ToString()
{
- return DoubleMinValue <= value && value <= DoubleMaxValue;
+ return ToString(CultureInfo.InvariantCulture);
}
///
- /// Returns the hash code for this instance.
+ /// Converts the numeric value of this instance to its equivalent string representation using
+ /// the specified culture-specific format information.
///
- ///
- /// The instance of to return the hash code for.
+ ///
+ /// An object that supplies culture-specific formatting information.
///
- ///
- /// A 32-bit signed integer that is the hash code for this instance.
- ///
- private int GetHashCode(Rational rational)
+ ///
+ public string ToString(IFormatProvider provider)
{
- return ((rational.Numerator * 397) ^ rational.Denominator).GetHashCode();
+ BigRational rational = new BigRational(Numerator, Denominator);
+ return rational.ToString(provider);
}
}
}
\ No newline at end of file
diff --git a/src/ImageProcessorCore/Numerics/SignedRational.cs b/src/ImageProcessorCore/Numerics/SignedRational.cs
new file mode 100644
index 000000000..d216b30d4
--- /dev/null
+++ b/src/ImageProcessorCore/Numerics/SignedRational.cs
@@ -0,0 +1,199 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageProcessorCore
+{
+ using System;
+ using System.Globalization;
+
+ ///
+ /// Represents a number that can be expressed as a fraction.
+ ///
+ ///
+ /// This is a very simplified implimentation of a rational number designed for use with metadata only.
+ ///
+ public struct SignedRational : IEquatable
+ {
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ ///The to convert to an instance of this type.
+ public SignedRational(double value)
+ : this(value, false)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ ///The to convert to an instance of this type.
+ ///Specifies if the instance should be created with the best precision possible.
+ public SignedRational(double value, bool bestPrecision)
+ {
+ BigRational rational = new BigRational(value, bestPrecision);
+
+ Numerator = (int)rational.Numerator;
+ Denominator = (int)rational.Denominator;
+ }
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// The integer to create the rational from.
+ public SignedRational(int value)
+ : this(value, 1)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// The number above the line in a vulgar fraction showing how many of the parts indicated by the denominator are taken.
+ /// The number below the line in a vulgar fraction; a divisor.
+ public SignedRational(int numerator, int denominator)
+ : this(numerator, denominator, true)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// The number above the line in a vulgar fraction showing how many of the parts indicated by the denominator are taken.
+ /// The number below the line in a vulgar fraction; a divisor.
+ /// Specified if the rational should be simplified.
+ public SignedRational(int numerator, int denominator, bool simplify)
+ {
+ BigRational rational = new BigRational(numerator, denominator, simplify);
+
+ Numerator = (int)rational.Numerator;
+ Denominator = (int)rational.Denominator;
+ }
+
+ ///
+ /// Determines whether the specified instances are considered equal.
+ ///
+ /// The first to compare.
+ /// The second to compare.
+ ///
+ public static bool operator ==(SignedRational left, SignedRational right)
+ {
+ return Equals(left, right);
+ }
+
+ ///
+ /// Determines whether the specified instances are not considered equal.
+ ///
+ /// The first to compare.
+ /// The second to compare.
+ ///
+ public static bool operator !=(SignedRational left, SignedRational right)
+ {
+ return !Equals(left, right);
+ }
+
+ ///
+ /// Gets the numerator of a number.
+ ///
+ public int Numerator
+ {
+ get;
+ private set;
+ }
+
+ ///
+ /// Gets the denominator of a number.
+ ///
+ public int Denominator
+ {
+ get;
+ private set;
+ }
+
+ ///
+ /// Determines whether the specified is equal to this .
+ ///
+ ///The to compare this with.
+ public override bool Equals(object obj)
+ {
+ if (obj is SignedRational)
+ return Equals((SignedRational)obj);
+
+ return false;
+ }
+
+ ///
+ /// Determines whether the specified is equal to this .
+ ///
+ ///The to compare this with.
+ public bool Equals(SignedRational other)
+ {
+ BigRational left = new BigRational(Numerator, Denominator);
+ BigRational right = new BigRational(other.Numerator, other.Denominator);
+
+ return left.Equals(right);
+ }
+
+ ///
+ /// Converts the specified to an instance of this type.
+ ///
+ ///The to convert to an instance of this type.
+ public static SignedRational FromDouble(double value)
+ {
+ return new SignedRational(value, false);
+ }
+
+ ///
+ /// Converts the specified to an instance of this type.
+ ///
+ ///The to convert to an instance of this type.
+ ///Specifies if the instance should be created with the best precision possible.
+ public static SignedRational FromDouble(double value, bool bestPrecision)
+ {
+ return new SignedRational(value, bestPrecision);
+ }
+
+ ///
+ /// Serves as a hash of this type.
+ ///
+ public override int GetHashCode()
+ {
+ BigRational self = new BigRational(Numerator, Denominator);
+ return self.GetHashCode();
+ }
+
+ ///
+ /// Converts a rational number to the nearest .
+ ///
+ ///
+ /// The .
+ ///
+ public double ToDouble()
+ {
+ return Numerator / (double)Denominator;
+ }
+
+ ///
+ /// Converts the numeric value of this instance to its equivalent string representation.
+ ///
+ public override string ToString()
+ {
+ return ToString(CultureInfo.InvariantCulture);
+ }
+
+ ///
+ /// Converts the numeric value of this instance to its equivalent string representation using
+ /// the specified culture-specific format information.
+ ///
+ ///
+ /// An object that supplies culture-specific formatting information.
+ ///
+ ///
+ public string ToString(IFormatProvider provider)
+ {
+ BigRational rational = new BigRational(Numerator, Denominator);
+ return rational.ToString(provider);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageProcessorCore/Profiles/Exif/ExifProfile.cs b/src/ImageProcessorCore/Profiles/Exif/ExifProfile.cs
index 638d721a7..2c1509fd0 100644
--- a/src/ImageProcessorCore/Profiles/Exif/ExifProfile.cs
+++ b/src/ImageProcessorCore/Profiles/Exif/ExifProfile.cs
@@ -2,9 +2,9 @@
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
//
+
namespace ImageProcessorCore
{
- using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
diff --git a/src/ImageProcessorCore/Profiles/Exif/ExifReader.cs b/src/ImageProcessorCore/Profiles/Exif/ExifReader.cs
index 333a00d0a..546d5b846 100644
--- a/src/ImageProcessorCore/Profiles/Exif/ExifReader.cs
+++ b/src/ImageProcessorCore/Profiles/Exif/ExifReader.cs
@@ -442,13 +442,13 @@ namespace ImageProcessorCore
{
if (!this.ValidateArray(data, 8, 4))
{
- return Rational.Zero;
+ return new Rational();
}
uint numerator = BitConverter.ToUInt32(data, 0);
uint denominator = BitConverter.ToUInt32(data, 4);
- return new Rational(numerator, denominator);
+ return new Rational(numerator, denominator, false);
}
private sbyte ToSignedByte(byte[] data)
@@ -466,17 +466,17 @@ namespace ImageProcessorCore
return BitConverter.ToInt32(data, 0);
}
- private Rational ToSignedRational(byte[] data)
+ private SignedRational ToSignedRational(byte[] data)
{
if (!this.ValidateArray(data, 8, 4))
{
- return Rational.Zero;
+ return new SignedRational();
}
int numerator = BitConverter.ToInt32(data, 0);
int denominator = BitConverter.ToInt32(data, 4);
- return new Rational(numerator, denominator);
+ return new SignedRational(numerator, denominator, false);
}
private short ToSignedShort(byte[] data)
diff --git a/src/ImageProcessorCore/Profiles/Exif/ExifValue.cs b/src/ImageProcessorCore/Profiles/Exif/ExifValue.cs
index 3fd195b4e..a79bc85ef 100644
--- a/src/ImageProcessorCore/Profiles/Exif/ExifValue.cs
+++ b/src/ImageProcessorCore/Profiles/Exif/ExifValue.cs
@@ -539,13 +539,12 @@ namespace ImageProcessorCore
case ExifDataType.DoubleFloat:
Guard.IsTrue(type == typeof(double), nameof(value), $"Value should be a double{(this.IsArray ? " array." : ".")}");
break;
- case ExifDataType.Rational:
- case ExifDataType.SignedRational:
- Guard.IsTrue(type == typeof(Rational), nameof(value), $"Value should be a Rational{(this.IsArray ? " array." : ".")}");
- break;
case ExifDataType.Long:
Guard.IsTrue(type == typeof(uint), nameof(value), $"Value should be an unsigned int{(this.IsArray ? " array." : ".")}");
break;
+ case ExifDataType.Rational:
+ Guard.IsTrue(type == typeof(Rational), nameof(value), $"Value should be a Rational{(this.IsArray ? " array." : ".")}");
+ break;
case ExifDataType.Short:
Guard.IsTrue(type == typeof(ushort), nameof(value), $"Value should be an unsigned short{(this.IsArray ? " array." : ".")}");
break;
@@ -555,6 +554,9 @@ namespace ImageProcessorCore
case ExifDataType.SignedLong:
Guard.IsTrue(type == typeof(int), nameof(value), $"Value should be an int{(this.IsArray ? " array." : ".")}");
break;
+ case ExifDataType.SignedRational:
+ Guard.IsTrue(type == typeof(SignedRational), nameof(value), $"Value should be a SignedRational{(this.IsArray ? " array." : ".")}");
+ break;
case ExifDataType.SignedShort:
Guard.IsTrue(type == typeof(short), nameof(value), $"Value should be a short{(this.IsArray ? " array." : ".")}");
break;
diff --git a/src/ImageProcessorCore/Profiles/Exif/ExifWriter.cs b/src/ImageProcessorCore/Profiles/Exif/ExifWriter.cs
index 269ce52c4..e89b0d1a9 100644
--- a/src/ImageProcessorCore/Profiles/Exif/ExifWriter.cs
+++ b/src/ImageProcessorCore/Profiles/Exif/ExifWriter.cs
@@ -329,17 +329,16 @@ namespace ImageProcessorCore
private int WriteRational(Rational value, byte[] destination, int offset)
{
- // Ensure no overflow
- Write(BitConverter.GetBytes((uint)(value.Numerator * (value.ToDouble() < 0.0 ? -1 : 1))), destination, offset);
- Write(BitConverter.GetBytes((uint)value.Denominator), destination, offset + 4);
+ Write(BitConverter.GetBytes(value.Numerator), destination, offset);
+ Write(BitConverter.GetBytes(value.Denominator), destination, offset + 4);
return offset + 8;
}
- private int WriteSignedRational(Rational value, byte[] destination, int offset)
+ private int WriteSignedRational(SignedRational value, byte[] destination, int offset)
{
- Write(BitConverter.GetBytes((int)value.Numerator), destination, offset);
- Write(BitConverter.GetBytes((int)value.Denominator), destination, offset + 4);
+ Write(BitConverter.GetBytes(value.Numerator), destination, offset);
+ Write(BitConverter.GetBytes(value.Denominator), destination, offset + 4);
return offset + 8;
}
@@ -370,7 +369,7 @@ namespace ImageProcessorCore
case ExifDataType.SignedShort:
return Write(BitConverter.GetBytes((short)value), destination, offset);
case ExifDataType.SignedRational:
- return this.WriteSignedRational((Rational)value, destination, offset);
+ return this.WriteSignedRational((SignedRational)value, destination, offset);
case ExifDataType.SingleFloat:
return Write(BitConverter.GetBytes((float)value), destination, offset);
default:
diff --git a/src/ImageProcessorCore/Quantizers/IQuantizer.cs b/src/ImageProcessorCore/Quantizers/IQuantizer.cs
index af4733b11..e0087a52e 100644
--- a/src/ImageProcessorCore/Quantizers/IQuantizer.cs
+++ b/src/ImageProcessorCore/Quantizers/IQuantizer.cs
@@ -15,7 +15,7 @@ namespace ImageProcessorCore.Quantizers
where TPacked : struct
{
///
- /// Quantize an image and return the resulting outpuTColor pixels.
+ /// Quantize an image and return the resulting output pixels.
///
/// The image to quantize.
/// The maximum number of colors to return.
diff --git a/src/ImageProcessorCore/Quantizers/Octree/OctreeQuantizer.cs b/src/ImageProcessorCore/Quantizers/Octree/OctreeQuantizer.cs
index ac5c142f9..89d18575a 100644
--- a/src/ImageProcessorCore/Quantizers/Octree/OctreeQuantizer.cs
+++ b/src/ImageProcessorCore/Quantizers/Octree/OctreeQuantizer.cs
@@ -74,9 +74,7 @@ namespace ImageProcessorCore.Quantizers
///
/// Override this to process the pixel in the second pass of the algorithm
///
- ///
- /// The pixel to quantize
- ///
+ /// The pixel to quantize
///
/// The quantized value
///
@@ -197,7 +195,7 @@ namespace ImageProcessorCore.Quantizers
///
public void AddColor(TColor pixel)
{
- TPacked packed = pixel.PackedValue; //.GetPackedValue();
+ TPacked packed = pixel.PackedValue;
// Check if this request is for the same color as the last
if (this.previousColor.Equals(packed))
{
@@ -224,11 +222,9 @@ namespace ImageProcessorCore.Quantizers
///
/// Convert the nodes in the Octree to a palette with a maximum of colorCount colors
///
- ///
- /// The maximum number of colors
- ///
+ /// The maximum number of colors
///
- /// An with the palletized colors
+ /// An with the palletized colors
///
public List Palletize(int colorCount)
{
@@ -249,9 +245,7 @@ namespace ImageProcessorCore.Quantizers
///
/// Get the palette index for the passed color
///
- ///
- /// The containing the pixel data.
- ///
+ /// The containing the pixel data.
///
/// The index of the given structure.
///
@@ -449,12 +443,8 @@ namespace ImageProcessorCore.Quantizers
///
/// Traverse the tree, building up the color palette
///
- ///
- /// The palette
- ///
- ///
- /// The current palette index
- ///
+ /// The palette
+ /// The current palette index
public void ConstructPalette(List palette, ref int index)
{
if (this.leaf)
diff --git a/src/ImageProcessorCore/Quantizers/Octree/Quantizer.cs b/src/ImageProcessorCore/Quantizers/Octree/Quantizer.cs
index 7bda2d4ab..a5d933d4e 100644
--- a/src/ImageProcessorCore/Quantizers/Octree/Quantizer.cs
+++ b/src/ImageProcessorCore/Quantizers/Octree/Quantizer.cs
@@ -11,6 +11,8 @@ namespace ImageProcessorCore.Quantizers
///
/// Encapsulates methods to calculate the color palette of an image.
///
+ /// The pixel format.
+ /// The packed format. uint, long, float.
public abstract class Quantizer : IQuantizer
where TColor : IPackedVector
where TPacked : struct
@@ -98,10 +100,10 @@ namespace ImageProcessorCore.Quantizers
/// Execute a second pass through the bitmap
///
/// The source image.
- /// The outpuTColor pixel array
+ /// The output pixel array
/// The width in pixels of the image
/// The height in pixels of the image
- protected virtual void SecondPass(PixelAccessor source, byte[] output, int width, int height)
+ protected virtual void SecondPass(PixelAccessor source, byte[] output, int width, int height)
{
Parallel.For(
0,
diff --git a/src/ImageProcessorCore/Quantizers/Quantize.cs b/src/ImageProcessorCore/Quantizers/Quantize.cs
index ea0102d59..c6b72430c 100644
--- a/src/ImageProcessorCore/Quantizers/Quantize.cs
+++ b/src/ImageProcessorCore/Quantizers/Quantize.cs
@@ -3,10 +3,10 @@
// Licensed under the Apache License, Version 2.0.
//
-using ImageProcessorCore.Quantizers;
-
namespace ImageProcessorCore
{
+ using ImageProcessorCore.Quantizers;
+
///
/// Extension methods for the type.
///
diff --git a/src/ImageProcessorCore/Quantizers/QuantizedImage.cs b/src/ImageProcessorCore/Quantizers/QuantizedImage.cs
index f95483f37..84ebcadfe 100644
--- a/src/ImageProcessorCore/Quantizers/QuantizedImage.cs
+++ b/src/ImageProcessorCore/Quantizers/QuantizedImage.cs
@@ -14,8 +14,8 @@ namespace ImageProcessorCore.Quantizers
/// The pixel format.
/// The packed format. uint, long, float.
public class QuantizedImage
- where TColor : IPackedVector
- where TPacked : struct
+ where TColor : IPackedVector
+ where TPacked : struct
{
///
/// Initializes a new instance of the class.
diff --git a/src/ImageProcessorCore/Quantizers/Wu/WuQuantizer.cs b/src/ImageProcessorCore/Quantizers/Wu/WuQuantizer.cs
index 2ee802a5d..ed4820306 100644
--- a/src/ImageProcessorCore/Quantizers/Wu/WuQuantizer.cs
+++ b/src/ImageProcessorCore/Quantizers/Wu/WuQuantizer.cs
@@ -104,7 +104,7 @@ namespace ImageProcessorCore.Quantizers
private readonly byte[] tag;
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
public WuQuantizer()
{
diff --git a/src/ImageProcessorCore/Samplers/AutoOrient.cs b/src/ImageProcessorCore/Samplers/AutoOrient.cs
index 33f7902c2..a0dac5d67 100644
--- a/src/ImageProcessorCore/Samplers/AutoOrient.cs
+++ b/src/ImageProcessorCore/Samplers/AutoOrient.cs
@@ -17,7 +17,7 @@ namespace ImageProcessorCore
///
/// The pixel format.
/// The packed format. uint, long, float.
- /// The image to crop.
+ /// The image to auto rotate.
/// The
public static Image AutoOrient(this Image source, ProgressEventHandler progressHandler = null)
where TColor : IPackedVector
@@ -27,11 +27,6 @@ namespace ImageProcessorCore
switch (orientation)
{
- case Orientation.Unknown:
- case Orientation.TopLeft:
- default:
- return source;
-
case Orientation.TopRight:
return source.Flip(FlipType.Horizontal, progressHandler);
@@ -42,23 +37,33 @@ namespace ImageProcessorCore
return source.Flip(FlipType.Vertical, progressHandler);
case Orientation.LeftTop:
- return source
- .Rotate(RotateType.Rotate90, progressHandler)
- .Flip(FlipType.Horizontal, progressHandler);
+ return source.Rotate(RotateType.Rotate90, progressHandler)
+ .Flip(FlipType.Horizontal, progressHandler);
case Orientation.RightTop:
return source.Rotate(RotateType.Rotate90, progressHandler);
case Orientation.RightBottom:
- return source
- .Flip(FlipType.Vertical, progressHandler)
- .Rotate(RotateType.Rotate270, progressHandler);
+ return source.Flip(FlipType.Vertical, progressHandler)
+ .Rotate(RotateType.Rotate270, progressHandler);
case Orientation.LeftBottom:
return source.Rotate(RotateType.Rotate270, progressHandler);
+
+ case Orientation.Unknown:
+ case Orientation.TopLeft:
+ default:
+ return source;
}
}
+ ///
+ /// Returns the current EXIF orientation
+ ///
+ /// The pixel format.
+ /// The packed format. uint, long, float.
+ /// The image to auto rotate.
+ /// The
private static Orientation GetExifOrientation(Image source)
where TColor : IPackedVector
where TPacked : struct
@@ -81,4 +86,4 @@ namespace ImageProcessorCore
return orientation;
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageProcessorCore/Samplers/Options/ResizeHelper.cs b/src/ImageProcessorCore/Samplers/Options/ResizeHelper.cs
index eab845cff..82a98c3c3 100644
--- a/src/ImageProcessorCore/Samplers/Options/ResizeHelper.cs
+++ b/src/ImageProcessorCore/Samplers/Options/ResizeHelper.cs
@@ -17,7 +17,8 @@ namespace ImageProcessorCore
///
/// Calculates the target location and bounds to perform the resize operation against.
///
- /// The type of pixels contained within the image.
+ /// The pixel format.
+ /// The packed format. uint, long, float.
/// The source image.
/// The resize options.
///
@@ -49,7 +50,8 @@ namespace ImageProcessorCore
///
/// Calculates the target rectangle for crop mode.
///
- /// The type of pixels contained within the image.
+ /// The pixel format.
+ /// The packed format. uint, long, float.
/// The source image.
/// The resize options.
///
@@ -169,7 +171,8 @@ namespace ImageProcessorCore
///
/// Calculates the target rectangle for pad mode.
///
- /// The type of pixels contained within the image.
+ /// The pixel format.
+ /// The packed format. uint, long, float.
/// The source image.
/// The resize options.
///
@@ -251,7 +254,8 @@ namespace ImageProcessorCore
///
/// Calculates the target rectangle for box pad mode.
///
- /// The type of pixels contained within the image.
+ /// The pixel format.
+ /// The packed format. uint, long, float.
/// The source image.
/// The resize options.
///
@@ -339,7 +343,8 @@ namespace ImageProcessorCore
///
/// Calculates the target rectangle for max mode.
///
- /// The type of pixels contained within the image.
+ /// The pixel format.
+ /// The packed format. uint, long, float.
/// The source image.
/// The resize options.
///
@@ -381,7 +386,8 @@ namespace ImageProcessorCore
///
/// Calculates the target rectangle for min mode.
///
- /// The type of pixels contained within the image.
+ /// The pixel format.
+ /// The packed format. uint, long, float.
/// The source image.
/// The resize options.
///
diff --git a/src/ImageProcessorCore/Samplers/Processors/EntropyCropProcessor.cs b/src/ImageProcessorCore/Samplers/Processors/EntropyCropProcessor.cs
index f20b7bce1..1f858631d 100644
--- a/src/ImageProcessorCore/Samplers/Processors/EntropyCropProcessor.cs
+++ b/src/ImageProcessorCore/Samplers/Processors/EntropyCropProcessor.cs
@@ -27,7 +27,7 @@ namespace ImageProcessorCore.Processors
/// Initializes a new instance of the class.
///
/// The threshold to split the image. Must be between 0 and 1.
- ///
+ ///
/// is less than 0 or is greater than 1.
///
public EntropyCropProcessor(float threshold)
@@ -55,7 +55,7 @@ namespace ImageProcessorCore.Processors
// Search for the first white pixels
Rectangle rectangle = ImageMaths.GetFilteredBoundingRectangle(temp, 0);
- // Reset the targeTColor pixel to the correct size.
+ // Reset the target pixel to the correct size.
target.SetPixels(rectangle.Width, rectangle.Height, new TColor[rectangle.Width * rectangle.Height]);
this.cropRectangle = rectangle;
}
diff --git a/src/ImageProcessorCore/Samplers/Processors/ImageSampler.cs b/src/ImageProcessorCore/Samplers/Processors/ImageSampler.cs
index c1d4d5c70..1256897db 100644
--- a/src/ImageProcessorCore/Samplers/Processors/ImageSampler.cs
+++ b/src/ImageProcessorCore/Samplers/Processors/ImageSampler.cs
@@ -16,4 +16,4 @@ namespace ImageProcessorCore.Processors
where TPacked : struct
{
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageProcessorCore/Samplers/Processors/RotateProcessor.cs b/src/ImageProcessorCore/Samplers/Processors/RotateProcessor.cs
index df3eea635..be005f252 100644
--- a/src/ImageProcessorCore/Samplers/Processors/RotateProcessor.cs
+++ b/src/ImageProcessorCore/Samplers/Processors/RotateProcessor.cs
@@ -2,6 +2,9 @@
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
//
+
+using System;
+
namespace ImageProcessorCore.Processors
{
using System.Numerics;
@@ -34,7 +37,9 @@ namespace ImageProcessorCore.Processors
///
protected override void OnApply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle)
{
- if (Angle == 0 || Angle == 90 || Angle == 180 || Angle == 270)
+ const float Epsilon = .0001F;
+
+ if (Math.Abs(Angle) < Epsilon || Math.Abs(Angle - 90) < Epsilon || Math.Abs(Angle - 180) < Epsilon || Math.Abs(Angle - 270) < Epsilon)
{
return;
}
@@ -89,25 +94,26 @@ namespace ImageProcessorCore.Processors
///
private bool OptimizedApply(ImageBase target, ImageBase source)
{
- if (Angle == 0)
+ const float Epsilon = .0001F;
+ if (Math.Abs(Angle) < Epsilon)
{
target.ClonePixels(target.Width, target.Height, source.Pixels);
return true;
}
- if (Angle == 90)
+ if (Math.Abs(Angle - 90) < Epsilon)
{
this.Rotate90(target, source);
return true;
}
- if (Angle == 180)
+ if (Math.Abs(Angle - 180) < Epsilon)
{
this.Rotate180(target, source);
return true;
}
- if (Angle == 270)
+ if (Math.Abs(Angle - 270) < Epsilon)
{
this.Rotate270(target, source);
return true;
diff --git a/src/ImageProcessorCore/Samplers/Resamplers/NearestNeighborResampler.cs b/src/ImageProcessorCore/Samplers/Resamplers/NearestNeighborResampler.cs
index bcd9a58b1..58b6a9d58 100644
--- a/src/ImageProcessorCore/Samplers/Resamplers/NearestNeighborResampler.cs
+++ b/src/ImageProcessorCore/Samplers/Resamplers/NearestNeighborResampler.cs
@@ -7,7 +7,7 @@ namespace ImageProcessorCore
{
///
/// The function implements the nearest neighbour algorithm. This uses an unscaled filter
- /// which will select the closesTColor pixel to the new pixels position.
+ /// which will select the closest pixel to the new pixels position.
///
public class NearestNeighborResampler : IResampler
{
diff --git a/src/ImageProcessorCore/Samplers/RotateFlip.cs b/src/ImageProcessorCore/Samplers/RotateFlip.cs
index 0cd406038..8bba64ca5 100644
--- a/src/ImageProcessorCore/Samplers/RotateFlip.cs
+++ b/src/ImageProcessorCore/Samplers/RotateFlip.cs
@@ -25,9 +25,7 @@ namespace ImageProcessorCore
where TColor : IPackedVector
where TPacked : struct
{
- return source
- .Rotate(rotateType, progressHandler)
- .Flip(flipType, progressHandler);
+ return source.Rotate(rotateType, progressHandler).Flip(flipType, progressHandler);
}
}
}
diff --git a/tests/ImageProcessorCore.Benchmarks/General/Copy.cs b/tests/ImageProcessorCore.Benchmarks/General/ArrayCopy.cs
similarity index 96%
rename from tests/ImageProcessorCore.Benchmarks/General/Copy.cs
rename to tests/ImageProcessorCore.Benchmarks/General/ArrayCopy.cs
index de4dadffb..349c94fa3 100644
--- a/tests/ImageProcessorCore.Benchmarks/General/Copy.cs
+++ b/tests/ImageProcessorCore.Benchmarks/General/ArrayCopy.cs
@@ -5,7 +5,7 @@ namespace ImageProcessorCore.Benchmarks.General
{
using BenchmarkDotNet.Attributes;
- public class Copy
+ public class ArrayCopy
{
private double[] source = new double[10000];
diff --git a/tests/ImageProcessorCore.Benchmarks/Image/CopyPixels.cs b/tests/ImageProcessorCore.Benchmarks/Image/CopyPixels.cs
new file mode 100644
index 000000000..df0706bc6
--- /dev/null
+++ b/tests/ImageProcessorCore.Benchmarks/Image/CopyPixels.cs
@@ -0,0 +1,57 @@
+namespace ImageProcessorCore.Benchmarks.Image
+{
+ using System.Threading.Tasks;
+
+ using BenchmarkDotNet.Attributes;
+
+ using CoreColor = ImageProcessorCore.Color;
+ using CoreImage = ImageProcessorCore.Image;
+
+ public class CopyPixels
+ {
+ [Benchmark(Description = "Copy by Pixel")]
+ public CoreColor CopyByPixel()
+ {
+ CoreImage source = new CoreImage(1024, 768);
+ CoreImage target = new CoreImage(1024, 768);
+ using (PixelAccessor sourcePixels = source.Lock())
+ using (PixelAccessor targetPixels = target.Lock())
+ {
+ Parallel.For(
+ 0,
+ source.Height,
+ Bootstrapper.Instance.ParallelOptions,
+ y =>
+ {
+ for (int x = 0; x < source.Width; x++)
+ {
+ targetPixels[x, y] = sourcePixels[x, y];
+ }
+ });
+
+ return targetPixels[0, 0];
+ }
+ }
+
+ [Benchmark(Description = "Copy by Row")]
+ public CoreColor CopyByRow()
+ {
+ CoreImage source = new CoreImage(1024, 768);
+ CoreImage target = new CoreImage(1024, 768);
+ using (PixelAccessor sourcePixels = source.Lock())
+ using (PixelAccessor targetPixels = target.Lock())
+ {
+ Parallel.For(
+ 0,
+ source.Height,
+ Bootstrapper.Instance.ParallelOptions,
+ y =>
+ {
+ sourcePixels.CopyRow(0, y, targetPixels, 0, y, source.Width);
+ });
+
+ return targetPixels[0, 0];
+ }
+ }
+ }
+}
diff --git a/tests/ImageProcessorCore.Benchmarks/Samplers/Crop.cs b/tests/ImageProcessorCore.Benchmarks/Samplers/Crop.cs
index 4eaeea6ec..ef7cb9722 100644
--- a/tests/ImageProcessorCore.Benchmarks/Samplers/Crop.cs
+++ b/tests/ImageProcessorCore.Benchmarks/Samplers/Crop.cs
@@ -12,7 +12,7 @@
[Benchmark(Baseline = true, Description = "System.Drawing Crop")]
public Size CropSystemDrawing()
{
- using (Bitmap source = new Bitmap(400, 400))
+ using (Bitmap source = new Bitmap(800, 800))
{
using (Bitmap destination = new Bitmap(100, 100))
{
@@ -32,7 +32,7 @@
[Benchmark(Description = "ImageProcessorCore Crop")]
public CoreSize CropResizeCore()
{
- CoreImage image = new CoreImage(400, 400);
+ CoreImage image = new CoreImage(800, 800);
image.Crop(100, 100);
return new CoreSize(image.Width, image.Height);
}
diff --git a/tests/ImageProcessorCore.Tests/Helpers/GuardTests.cs b/tests/ImageProcessorCore.Tests/Helpers/GuardTests.cs
index 7c33470c3..b92c4e0a8 100644
--- a/tests/ImageProcessorCore.Tests/Helpers/GuardTests.cs
+++ b/tests/ImageProcessorCore.Tests/Helpers/GuardTests.cs
@@ -207,7 +207,7 @@ namespace ImageProcessorCore.Tests.Helpers
[Fact]
public void IsTrueThrowsWhenArgIsFalse()
{
- Assert.Throws(() => Guard.IsTrue(false, "foo"));
+ Assert.Throws(() => Guard.IsTrue(false, "foo", "message"));
}
///
@@ -216,7 +216,7 @@ namespace ImageProcessorCore.Tests.Helpers
[Fact]
public void IsTrueDoesThrowsWhenArgIsTrue()
{
- Exception ex = Record.Exception(() => Guard.IsTrue(true, "foo"));
+ Exception ex = Record.Exception(() => Guard.IsTrue(true, "foo", "message"));
Assert.Null(ex);
}
@@ -226,7 +226,7 @@ namespace ImageProcessorCore.Tests.Helpers
[Fact]
public void IsFalseThrowsWhenArgIsFalse()
{
- Assert.Throws(() => Guard.IsFalse(true, "foo"));
+ Assert.Throws(() => Guard.IsFalse(true, "foo", "message"));
}
///
@@ -235,7 +235,7 @@ namespace ImageProcessorCore.Tests.Helpers
[Fact]
public void IsFalseDoesThrowsWhenArgIsTrue()
{
- Exception ex = Record.Exception(() => Guard.IsFalse(false, "foo"));
+ Exception ex = Record.Exception(() => Guard.IsFalse(false, "foo", "message"));
Assert.Null(ex);
}
}
diff --git a/tests/ImageProcessorCore.Tests/Numerics/RationalTests.cs b/tests/ImageProcessorCore.Tests/Numerics/RationalTests.cs
index 246349f82..e83ec5118 100644
--- a/tests/ImageProcessorCore.Tests/Numerics/RationalTests.cs
+++ b/tests/ImageProcessorCore.Tests/Numerics/RationalTests.cs
@@ -22,6 +22,7 @@ namespace ImageProcessorCore.Tests
Rational r2 = new Rational(3, 2);
Assert.Equal(r1, r2);
+ Assert.True(r1 == r2);
Rational r3 = new Rational(7.55);
Rational r4 = new Rational(755, 100);
@@ -41,6 +42,7 @@ namespace ImageProcessorCore.Tests
Rational second = new Rational(100, 100);
Assert.NotEqual(first, second);
+ Assert.True(first != second);
}
///
@@ -49,9 +51,65 @@ namespace ImageProcessorCore.Tests
[Fact]
public void ConstructorAssignsProperties()
{
- Rational first = new Rational(4, 5);
- Assert.Equal(4, first.Numerator);
- Assert.Equal(5, first.Denominator);
+ Rational rational = new Rational(7, 55);
+ Assert.Equal(7U, rational.Numerator);
+ Assert.Equal(55U, rational.Denominator);
+
+ rational = new Rational(755, 100);
+ Assert.Equal(151U, rational.Numerator);
+ Assert.Equal(20U, rational.Denominator);
+
+ rational = new Rational(755, 100, false);
+ Assert.Equal(755U, rational.Numerator);
+ Assert.Equal(100U, rational.Denominator);
+
+ rational = new Rational(-7.55);
+ Assert.Equal(151U, rational.Numerator);
+ Assert.Equal(20U, rational.Denominator);
+
+ rational = new Rational(7);
+ Assert.Equal(7U, rational.Numerator);
+ Assert.Equal(1U, rational.Denominator);
+ }
+
+ [Fact]
+ public void Fraction()
+ {
+ Rational first = new Rational(1.0 / 1600);
+ Rational second = new Rational(1.0 / 1600, true);
+ Assert.False(first.Equals(second));
+ }
+
+ [Fact]
+ public void ToDouble()
+ {
+ Rational rational = new Rational(0, 0);
+ Assert.Equal(double.NaN, rational.ToDouble());
+
+ rational = new Rational(2, 0);
+ Assert.Equal(double.PositiveInfinity, rational.ToDouble());
+ }
+
+ [Fact]
+ public void ToStringRepresention()
+ {
+ Rational rational = new Rational(0, 0);
+ Assert.Equal("[ Indeterminate ]", rational.ToString());
+
+ rational = new Rational(double.PositiveInfinity);
+ Assert.Equal("[ PositiveInfinity ]", rational.ToString());
+
+ rational = new Rational(double.NegativeInfinity);
+ Assert.Equal("[ PositiveInfinity ]", rational.ToString());
+
+ rational = new Rational(0, 1);
+ Assert.Equal("0", rational.ToString());
+
+ rational = new Rational(2, 1);
+ Assert.Equal("2", rational.ToString());
+
+ rational = new Rational(1, 2);
+ Assert.Equal("1/2", rational.ToString());
}
}
}
\ No newline at end of file
diff --git a/tests/ImageProcessorCore.Tests/Numerics/SignedRationalTests.cs b/tests/ImageProcessorCore.Tests/Numerics/SignedRationalTests.cs
new file mode 100644
index 000000000..fff7f0fd3
--- /dev/null
+++ b/tests/ImageProcessorCore.Tests/Numerics/SignedRationalTests.cs
@@ -0,0 +1,122 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageProcessorCore.Tests
+{
+ using Xunit;
+
+ ///
+ /// Tests the struct.
+ ///
+ public class SignedRationalTests
+ {
+ ///
+ /// Tests the equality operators for equality.
+ ///
+ [Fact]
+ public void AreEqual()
+ {
+ SignedRational r1 = new SignedRational(3, 2);
+ SignedRational r2 = new SignedRational(3, 2);
+
+ Assert.Equal(r1, r2);
+ Assert.True(r1 == r2);
+
+ SignedRational r3 = new SignedRational(7.55);
+ SignedRational r4 = new SignedRational(755, 100);
+ SignedRational r5 = new SignedRational(151, 20);
+
+ Assert.Equal(r3, r4);
+ Assert.Equal(r4, r5);
+ }
+
+ ///
+ /// Tests the equality operators for inequality.
+ ///
+ [Fact]
+ public void AreNotEqual()
+ {
+ SignedRational first = new SignedRational(0, 100);
+ SignedRational second = new SignedRational(100, 100);
+
+ Assert.NotEqual(first, second);
+ Assert.True(first != second);
+ }
+
+ ///
+ /// Tests whether the Rational constructor correctly assign properties.
+ ///
+ [Fact]
+ public void ConstructorAssignsProperties()
+ {
+ SignedRational rational = new SignedRational(7, -55);
+ Assert.Equal(7, rational.Numerator);
+ Assert.Equal(-55, rational.Denominator);
+
+ rational = new SignedRational(-755, 100);
+ Assert.Equal(-151, rational.Numerator);
+ Assert.Equal(20, rational.Denominator);
+
+ rational = new SignedRational(-755, -100, false);
+ Assert.Equal(-755, rational.Numerator);
+ Assert.Equal(-100, rational.Denominator);
+
+ rational = new SignedRational(-151, -20);
+ Assert.Equal(-151, rational.Numerator);
+ Assert.Equal(-20, rational.Denominator);
+
+ rational = new SignedRational(-7.55);
+ Assert.Equal(-151, rational.Numerator);
+ Assert.Equal(20, rational.Denominator);
+
+ rational = new SignedRational(7);
+ Assert.Equal(7, rational.Numerator);
+ Assert.Equal(1, rational.Denominator);
+ }
+
+ [Fact]
+ public void Fraction()
+ {
+ SignedRational first = new SignedRational(1.0 / 1600);
+ SignedRational second = new SignedRational(1.0 / 1600, true);
+ Assert.False(first.Equals(second));
+ }
+
+ [Fact]
+ public void ToDouble()
+ {
+ SignedRational rational = new SignedRational(0, 0);
+ Assert.Equal(double.NaN, rational.ToDouble());
+
+ rational = new SignedRational(2, 0);
+ Assert.Equal(double.PositiveInfinity, rational.ToDouble());
+
+ rational = new SignedRational(-2, 0);
+ Assert.Equal(double.NegativeInfinity, rational.ToDouble());
+ }
+
+ [Fact]
+ public void ToStringRepresention()
+ {
+ SignedRational rational = new SignedRational(0, 0);
+ Assert.Equal("[ Indeterminate ]", rational.ToString());
+
+ rational = new SignedRational(double.PositiveInfinity);
+ Assert.Equal("[ PositiveInfinity ]", rational.ToString());
+
+ rational = new SignedRational(double.NegativeInfinity);
+ Assert.Equal("[ NegativeInfinity ]", rational.ToString());
+
+ rational = new SignedRational(0, 1);
+ Assert.Equal("0", rational.ToString());
+
+ rational = new SignedRational(2, 1);
+ Assert.Equal("2", rational.ToString());
+
+ rational = new SignedRational(1, 2);
+ Assert.Equal("1/2", rational.ToString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageProcessorCore.Tests/Profiles/Exif/ExifProfileTests.cs b/tests/ImageProcessorCore.Tests/Profiles/Exif/ExifProfileTests.cs
index 438e90336..988c7747d 100644
--- a/tests/ImageProcessorCore.Tests/Profiles/Exif/ExifProfileTests.cs
+++ b/tests/ImageProcessorCore.Tests/Profiles/Exif/ExifProfileTests.cs
@@ -64,12 +64,11 @@ namespace ImageProcessorCore.Tests
{
using (MemoryStream memStream = new MemoryStream())
{
- // double exposureTime = 1.0 / 1600;
- Rational exposureTime = new Rational(1, 1600);
+ double exposureTime = 1.0 / 1600;
ExifProfile profile = GetExifProfile();
- profile.SetValue(ExifTag.ExposureTime, exposureTime);
+ profile.SetValue(ExifTag.ExposureTime, new Rational(exposureTime));
Image image = new Image(1, 1);
image.ExifProfile = profile;
@@ -84,12 +83,12 @@ namespace ImageProcessorCore.Tests
ExifValue value = profile.GetValue(ExifTag.ExposureTime);
Assert.NotNull(value);
- Assert.Equal(exposureTime, value.Value);
+ Assert.NotEqual(exposureTime, ((Rational)value.Value).ToDouble());
memStream.Position = 0;
profile = GetExifProfile();
- profile.SetValue(ExifTag.ExposureTime, exposureTime);
+ profile.SetValue(ExifTag.ExposureTime, new Rational(exposureTime, true));
image.ExifProfile = profile;
image.SaveAsJpeg(memStream);
@@ -101,7 +100,7 @@ namespace ImageProcessorCore.Tests
Assert.NotNull(profile);
value = profile.GetValue(ExifTag.ExposureTime);
- TestValue(value, exposureTime);
+ Assert.Equal(exposureTime, ((Rational)value.Value).ToDouble());
}
}
@@ -111,104 +110,29 @@ namespace ImageProcessorCore.Tests
using (FileStream stream = File.OpenRead(TestImages.Jpg.Floorplan))
{
Image image = new Image(stream);
- image.ExifProfile.SetValue(ExifTag.ExposureBiasValue, Rational.PositiveInfinity);
+ image.ExifProfile.SetValue(ExifTag.ExposureBiasValue, new SignedRational(double.PositiveInfinity));
image = WriteAndRead(image);
ExifValue value = image.ExifProfile.GetValue(ExifTag.ExposureBiasValue);
Assert.NotNull(value);
- Assert.Equal(Rational.PositiveInfinity, value.Value);
+ Assert.Equal(new SignedRational(double.PositiveInfinity), value.Value);
- image.ExifProfile.SetValue(ExifTag.ExposureBiasValue, Rational.NegativeInfinity);
+ image.ExifProfile.SetValue(ExifTag.ExposureBiasValue, new SignedRational(double.NegativeInfinity));
image = WriteAndRead(image);
value = image.ExifProfile.GetValue(ExifTag.ExposureBiasValue);
Assert.NotNull(value);
- Assert.Equal(Rational.NegativeInfinity, value.Value);
+ Assert.Equal(new SignedRational(double.NegativeInfinity), value.Value);
- image.ExifProfile.SetValue(ExifTag.FlashEnergy, Rational.NegativeInfinity);
+ image.ExifProfile.SetValue(ExifTag.FlashEnergy, new Rational(double.NegativeInfinity));
image = WriteAndRead(image);
value = image.ExifProfile.GetValue(ExifTag.FlashEnergy);
Assert.NotNull(value);
- Assert.Equal(Rational.PositiveInfinity, value.Value);
+ Assert.Equal(new Rational(double.PositiveInfinity), value.Value);
}
}
- //[Fact]
- //public void WriteFraction()
- //{
- // using (MemoryStream memStream = new MemoryStream())
- // {
- // double exposureTime = 1.0 / 1600;
-
- // ExifProfile profile = GetExifProfile();
-
- // profile.SetValue(ExifTag.ExposureTime, exposureTime);
-
- // Image image = new Image(1, 1);
- // image.ExifProfile = profile;
-
- // image.SaveAsJpeg(memStream);
-
- // memStream.Position = 0;
- // image = new Image(memStream);
-
- // profile = image.ExifProfile;
- // Assert.NotNull(profile);
-
- // ExifValue value = profile.GetValue(ExifTag.ExposureTime);
- // Assert.NotNull(value);
- // Assert.NotEqual(exposureTime, value.Value);
-
- // memStream.Position = 0;
- // profile = GetExifProfile();
-
- // profile.SetValue(ExifTag.ExposureTime, exposureTime);
- // profile.BestPrecision = true;
- // image.ExifProfile = profile;
-
- // image.SaveAsJpeg(memStream);
-
- // memStream.Position = 0;
- // image = new Image(memStream);
-
- // profile = image.ExifProfile;
- // Assert.NotNull(profile);
-
- // value = profile.GetValue(ExifTag.ExposureTime);
- // TestValue(value, exposureTime);
- // }
- //}
-
- //[Fact]
- //public void ReadWriteInfinity()
- //{
- // using (FileStream stream = File.OpenRead(TestImages.Jpg.Floorplan))
- // {
- // Image image = new Image(stream);
- // image.ExifProfile.SetValue(ExifTag.ExposureBiasValue, double.PositiveInfinity);
-
- // image = WriteAndRead(image);
- // ExifValue value = image.ExifProfile.GetValue(ExifTag.ExposureBiasValue);
- // Assert.NotNull(value);
- // Assert.Equal(double.PositiveInfinity, value.Value);
-
- // image.ExifProfile.SetValue(ExifTag.ExposureBiasValue, double.NegativeInfinity);
-
- // image = WriteAndRead(image);
- // value = image.ExifProfile.GetValue(ExifTag.ExposureBiasValue);
- // Assert.NotNull(value);
- // Assert.Equal(double.NegativeInfinity, value.Value);
-
- // image.ExifProfile.SetValue(ExifTag.FlashEnergy, double.NegativeInfinity);
-
- // image = WriteAndRead(image);
- // value = image.ExifProfile.GetValue(ExifTag.FlashEnergy);
- // Assert.NotNull(value);
- // Assert.Equal(double.PositiveInfinity, value.Value);
- // }
- //}
-
[Fact]
public void SetValue()
{
@@ -224,11 +148,11 @@ namespace ImageProcessorCore.Tests
Assert.Throws(() => { value.Value = 15; });
- image.ExifProfile.SetValue(ExifTag.ShutterSpeedValue, new Rational(75.55));
+ image.ExifProfile.SetValue(ExifTag.ShutterSpeedValue, new SignedRational(75.55));
value = image.ExifProfile.GetValue(ExifTag.ShutterSpeedValue);
- TestValue(value, new Rational(7555, 100));
+ TestValue(value, new SignedRational(7555, 100));
Assert.Throws(() => { value.Value = 75; });
@@ -258,7 +182,7 @@ namespace ImageProcessorCore.Tests
TestValue(value, "ImageProcessorCore");
value = image.ExifProfile.GetValue(ExifTag.ShutterSpeedValue);
- TestValue(value, new Rational(75.55));
+ TestValue(value, new SignedRational(75.55));
value = image.ExifProfile.GetValue(ExifTag.XResolution);
TestValue(value, new Rational(150.0));
@@ -372,6 +296,12 @@ namespace ImageProcessorCore.Tests
Assert.Equal(expected, value.Value);
}
+ private static void TestValue(ExifValue value, SignedRational expected)
+ {
+ Assert.NotNull(value);
+ Assert.Equal(expected, value.Value);
+ }
+
private static void TestValue(ExifValue value, Rational[] expected)
{
Assert.NotNull(value);