diff --git a/src/ImageProcessor.UnitTests/Imaging/ColorUnitTests.cs b/src/ImageProcessor.UnitTests/Imaging/ColorUnitTests.cs
index 70fbfcddb..db88ca4f3 100644
--- a/src/ImageProcessor.UnitTests/Imaging/ColorUnitTests.cs
+++ b/src/ImageProcessor.UnitTests/Imaging/ColorUnitTests.cs
@@ -25,7 +25,7 @@ namespace ImageProcessor.UnitTests.Imaging
/// Tests the struct equality operators.
///
[Test]
- public void TestRGBAEquality()
+ public void TestRgbaEquality()
{
RgbaColor first = RgbaColor.FromColor(Color.White);
RgbaColor second = RgbaColor.FromColor(Color.White);
@@ -34,10 +34,10 @@ namespace ImageProcessor.UnitTests.Imaging
}
///
- /// Tests the struct equality operators.
+ /// Tests the struct equality operators.
///
[Test]
- public void TestHSLAEquality()
+ public void TestHslaEquality()
{
HslaColor first = HslaColor.FromColor(Color.White);
HslaColor second = HslaColor.FromColor(Color.White);
@@ -45,6 +45,18 @@ namespace ImageProcessor.UnitTests.Imaging
Assert.AreEqual(first, second);
}
+ ///
+ /// Tests the struct equality operators.
+ ///
+ [Test]
+ public void TestYCbCrEquality()
+ {
+ YCbCrColor first = YCbCrColor.FromColor(Color.White);
+ YCbCrColor second = YCbCrColor.FromColor(Color.White);
+
+ Assert.AreEqual(first, second);
+ }
+
///
/// Test conversion to and from a .
///
@@ -52,9 +64,13 @@ namespace ImageProcessor.UnitTests.Imaging
/// The expected output.
///
[Test]
+ [TestCase("#FFFFFF")]
[TestCase("#FEFFFE")]
+ [TestCase("#F0F8FF")]
[TestCase("#000000")]
[TestCase("#CCFF33")]
+ [TestCase("#00FF00")]
+ [TestCase("#FF00FF")]
[TestCase("#990000")]
[TestCase("#5C955C")]
[TestCase("#5C5C95")]
@@ -77,9 +93,13 @@ namespace ImageProcessor.UnitTests.Imaging
/// The expected output.
///
[Test]
+ [TestCase("#FFFFFF")]
[TestCase("#FEFFFE")]
+ [TestCase("#F0F8FF")]
[TestCase("#000000")]
[TestCase("#CCFF33")]
+ [TestCase("#00FF00")]
+ [TestCase("#FF00FF")]
[TestCase("#990000")]
[TestCase("#5C955C")]
[TestCase("#5C5C95")]
@@ -95,29 +115,33 @@ namespace ImageProcessor.UnitTests.Imaging
Assert.AreEqual(expected, result);
}
- /////
- ///// Test conversion to and from a .
- /////
- /////
- ///// The expected output.
- /////
- //[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "Reviewed. Suppression is OK here."),Test]
- //[TestCase("#FEFFFE")]
- //[TestCase("#000000")]
- //[TestCase("#CCFF33")]
- //[TestCase("#990000")]
- //[TestCase("#5C955C")]
- //[TestCase("#5C5C95")]
- //[TestCase("#3F3F66")]
- //[TestCase("#FFFFBB")]
- //[TestCase("#FF002B")]
- //[TestCase("#00ABFF")]
- //public void TestYCbCrConversion(string expected)
- //{
- // Color color = ColorTranslator.FromHtml(expected);
- // YCbCrColor yCbCrColor = YCbCrColor.FromColor(color);
- // string result = ColorTranslator.ToHtml(yCbCrColor);
- // Assert.AreEqual(expected, result);
- //}
+ ///
+ /// Test conversion to and from a .
+ ///
+ ///
+ /// The expected output.
+ ///
+ [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "Reviewed. Suppression is OK here."), Test]
+ [TestCase("#FFFFFF")]
+ [TestCase("#FEFFFE")]
+ [TestCase("#F0F8FF")]
+ [TestCase("#000000")]
+ [TestCase("#CCFF33")]
+ [TestCase("#00FF00")]
+ [TestCase("#FF00FF")]
+ [TestCase("#990000")]
+ [TestCase("#5C955C")]
+ [TestCase("#5C5C95")]
+ [TestCase("#3F3F66")]
+ [TestCase("#FFFFBB")]
+ [TestCase("#FF002B")]
+ [TestCase("#00ABFF")]
+ public void TestYCbCrConversion(string expected)
+ {
+ Color color = ColorTranslator.FromHtml(expected);
+ YCbCrColor yCbCrColor = YCbCrColor.FromColor(color);
+ string result = ColorTranslator.ToHtml(yCbCrColor);
+ Assert.AreEqual(expected, result);
+ }
}
}
diff --git a/src/ImageProcessor/Common/Extensions/DoubleExtensions.cs b/src/ImageProcessor/Common/Extensions/DoubleExtensions.cs
index acc5b12c3..1ce97d2ac 100644
--- a/src/ImageProcessor/Common/Extensions/DoubleExtensions.cs
+++ b/src/ImageProcessor/Common/Extensions/DoubleExtensions.cs
@@ -10,6 +10,8 @@
namespace ImageProcessor.Common.Extensions
{
+ using System;
+
///
/// Encapsulates a series of time saving extension methods to the class.
///
@@ -30,7 +32,7 @@ namespace ImageProcessor.Common.Extensions
///
public static byte ToByte(this double d)
{
- return (byte)((d > byte.MaxValue) ? byte.MaxValue : ((d < byte.MinValue) ? byte.MinValue : d));
+ return Convert.ToByte(Math.Max(0.0d, Math.Min(255d, d))); // ((d > byte.MaxValue) ? byte.MaxValue : ((d < byte.MinValue) ? byte.MinValue : d));
}
}
}
diff --git a/src/ImageProcessor/Imaging/Colors/HSLAColor.cs b/src/ImageProcessor/Imaging/Colors/HSLAColor.cs
index d42ee3a87..d989f4ed3 100644
--- a/src/ImageProcessor/Imaging/Colors/HSLAColor.cs
+++ b/src/ImageProcessor/Imaging/Colors/HSLAColor.cs
@@ -84,6 +84,7 @@ namespace ImageProcessor.Imaging.Colors
///
/// Gets the hue component.
+ /// A value ranging between 0 and 1.
///
public float H
{
@@ -95,6 +96,7 @@ namespace ImageProcessor.Imaging.Colors
///
/// Gets the luminosity component.
+ /// A value ranging between 0 and 1.
///
public float L
{
@@ -106,6 +108,7 @@ namespace ImageProcessor.Imaging.Colors
///
/// Gets the saturation component.
+ /// A value ranging between 0 and 1.
///
public float S
{
@@ -117,6 +120,7 @@ namespace ImageProcessor.Imaging.Colors
///
/// Gets the alpha component.
+ /// A value ranging between 0 and 1.
///
public float A
{
@@ -197,17 +201,11 @@ namespace ImageProcessor.Imaging.Colors
///
public static implicit operator HslaColor(Color color)
{
- HslaColor hslColor = new HslaColor(
- color.GetHue() / 360.0f,
- color.GetSaturation(),
- color.GetBrightness(),
- color.A / 255f);
-
- return hslColor;
+ return FromColor(color);
}
///
- /// Allows the implicit conversion of an instance of to a
+ /// Allows the implicit conversion of an instance of to a
/// .
///
///
@@ -218,14 +216,22 @@ namespace ImageProcessor.Imaging.Colors
///
public static implicit operator HslaColor(RgbaColor rgbaColor)
{
- Color color = rgbaColor;
- HslaColor hslColor = new HslaColor(
- color.GetHue() / 360.0f,
- color.GetSaturation(),
- color.GetBrightness(),
- color.A / 255f);
-
- return hslColor;
+ return FromColor(rgbaColor);
+ }
+
+ ///
+ /// Allows the implicit conversion of an instance of to a
+ /// .
+ ///
+ ///
+ /// The instance of to convert.
+ ///
+ ///
+ /// An instance of .
+ ///
+ public static implicit operator HslaColor(YCbCrColor ycbcrColor)
+ {
+ return FromColor(ycbcrColor);
}
///
@@ -277,29 +283,22 @@ namespace ImageProcessor.Imaging.Colors
///
public static implicit operator RgbaColor(HslaColor hslaColor)
{
- float r = 0, g = 0, b = 0;
- if (Math.Abs(hslaColor.l - 0) > .0001)
- {
- if (Math.Abs(hslaColor.s - 0) <= .0001)
- {
- r = g = b = hslaColor.l;
- }
- else
- {
- float temp2 = GetTemp2(hslaColor);
- float temp1 = (2.0f * hslaColor.l) - temp2;
-
- r = GetColorComponent(temp1, temp2, hslaColor.h + (1.0f / 3.0f));
- g = GetColorComponent(temp1, temp2, hslaColor.h);
- b = GetColorComponent(temp1, temp2, hslaColor.h - (1.0f / 3.0f));
- }
- }
+ return RgbaColor.FromColor(hslaColor);
+ }
- return RgbaColor.FromRgba(
- Convert.ToByte(255 * r),
- Convert.ToByte(255 * g),
- Convert.ToByte(255 * b),
- Convert.ToByte(255 * hslaColor.a));
+ ///
+ /// Allows the implicit conversion of an instance of to a
+ /// .
+ ///
+ ///
+ /// The instance of to convert.
+ ///
+ ///
+ /// An instance of .
+ ///
+ public static implicit operator YCbCrColor(HslaColor hslaColor)
+ {
+ return YCbCrColor.FromColor(hslaColor);
}
///
diff --git a/src/ImageProcessor/Imaging/Colors/RGBAColor.cs b/src/ImageProcessor/Imaging/Colors/RGBAColor.cs
index 38976154a..790e2ae09 100644
--- a/src/ImageProcessor/Imaging/Colors/RGBAColor.cs
+++ b/src/ImageProcessor/Imaging/Colors/RGBAColor.cs
@@ -191,22 +191,37 @@ namespace ImageProcessor.Imaging.Colors
///
public static implicit operator RgbaColor(Color color)
{
- return new RgbaColor(color);
+ return FromColor(color);
}
///
- /// Allows the implicit conversion of an instance of to a
+ /// Allows the implicit conversion of an instance of to a
/// .
///
- ///
- /// The instance of to convert.
+ ///
+ /// The instance of to convert.
///
///
/// An instance of .
///
- public static implicit operator RgbaColor(HslaColor color)
+ public static implicit operator RgbaColor(HslaColor hslaColor)
{
- return new RgbaColor(color);
+ return FromColor(hslaColor);
+ }
+
+ ///
+ /// Allows the implicit conversion of an instance of to a
+ /// .
+ ///
+ ///
+ /// The instance of to convert.
+ ///
+ ///
+ /// An instance of .
+ ///
+ public static implicit operator RgbaColor(YCbCrColor ycbcrColor)
+ {
+ return FromColor(ycbcrColor);
}
///
@@ -239,6 +254,21 @@ namespace ImageProcessor.Imaging.Colors
return HslaColor.FromColor(rgba);
}
+ ///
+ /// Allows the implicit conversion of an instance of to a
+ /// .
+ ///
+ ///
+ /// The instance of to convert.
+ ///
+ ///
+ /// An instance of .
+ ///
+ public static implicit operator YCbCrColor(RgbaColor rgba)
+ {
+ return YCbCrColor.FromColor(rgba);
+ }
+
///
/// Returns a that represents this instance.
///
diff --git a/src/ImageProcessor/Imaging/Colors/YCbCrColor.cs b/src/ImageProcessor/Imaging/Colors/YCbCrColor.cs
index d1a5497c5..8f1c001c8 100644
--- a/src/ImageProcessor/Imaging/Colors/YCbCrColor.cs
+++ b/src/ImageProcessor/Imaging/Colors/YCbCrColor.cs
@@ -4,7 +4,7 @@
// Licensed under the Apache License, Version 2.0.
//
//
-// Represents an YCbCr (luminance, chroma, chroma) color used in digital imaging systems.
+// Represents an YCbCr (luminance, chroma, chroma) color conforming to the ITU-R BT.601 standard used in digital imaging systems.
//
//
// --------------------------------------------------------------------------------------------------------------------
@@ -14,10 +14,8 @@ namespace ImageProcessor.Imaging.Colors
using System;
using System.Drawing;
- using ImageProcessor.Common.Extensions;
-
///
- /// Represents an YCbCr (luminance, chroma, chroma) color used in digital imaging systems.
+ /// Represents an YCbCr (luminance, chroma, chroma) color conforming to the ITU-R BT.601 standard used in digital imaging systems.
///
///
public struct YCbCrColor
@@ -50,13 +48,14 @@ namespace ImageProcessor.Imaging.Colors
/// The v chroma component.
private YCbCrColor(float y, float cb, float cr)
{
- this.y = y; //Math.Max(0.0f, Math.Min(1.0f, y));
- this.cb = cb; //Math.Max(-0.5f, Math.Min(0.5f, cb));
- this.cr = cr; //Math.Max(-0.5f, Math.Min(0.5f, cr));
+ this.y = Math.Max(0f, Math.Min(255f, y));
+ this.cb = Math.Max(-255f, Math.Min(255f, cb));
+ this.cr = Math.Max(-255f, Math.Min(255f, cr));
}
///
/// Gets the Y luminance component.
+ /// A value ranging between 0 and 255.
///
public float Y
{
@@ -68,23 +67,25 @@ namespace ImageProcessor.Imaging.Colors
///
/// Gets the U chroma component.
+ /// A value ranging between -255 and 255.
///
public float Cb
{
get
{
- return this.y;
+ return this.cb;
}
}
///
/// Gets the V chroma component.
+ /// A value ranging between -255 and 255.
///
public float Cr
{
get
{
- return this.y;
+ return this.cr;
}
}
@@ -114,12 +115,12 @@ namespace ImageProcessor.Imaging.Colors
///
public static YCbCrColor FromColor(Color color)
{
- float r = color.R;
- float g = color.G;
- float b = color.B;
+ byte r = color.R;
+ byte g = color.G;
+ byte b = color.B;
float y = (float)((0.299 * r) + (0.587 * g) + (0.114 * b));
- float cb = 128 - (float)((-0.168736 * r) - (0.331264 * g) + (0.5 * b));
+ float cb = 128 + (float)((-0.168736 * r) - (0.331264 * g) + (0.5 * b));
float cr = 128 + (float)((0.5 * r) - (0.418688 * g) - (0.081312 * b));
return new YCbCrColor(y, cb, cr);
@@ -140,24 +141,148 @@ namespace ImageProcessor.Imaging.Colors
return FromColor(color);
}
+ ///
+ /// Allows the implicit conversion of an instance of to a
+ /// .
+ ///
+ ///
+ /// The instance of to convert.
+ ///
+ ///
+ /// An instance of .
+ ///
+ public static implicit operator YCbCrColor(RgbaColor rgbaColor)
+ {
+ return FromColor(rgbaColor);
+ }
+
+ ///
+ /// Allows the implicit conversion of an instance of to a
+ /// .
+ ///
+ ///
+ /// The instance of to convert.
+ ///
+ ///
+ /// An instance of .
+ ///
+ public static implicit operator YCbCrColor(HslaColor hslaColor)
+ {
+ return FromColor(hslaColor);
+ }
+
///
/// Allows the implicit conversion of an instance of to a
/// .
///
- ///
+ ///
/// The instance of to convert.
///
///
/// An instance of .
///
- public static implicit operator Color(YCbCrColor ycbcr)
+ public static implicit operator Color(YCbCrColor ycbcrColor)
{
- byte r = Convert.ToInt32(ycbcr.Y + (1.402 * (ycbcr.Cr - 128))).ToByte();
- byte g = Convert.ToInt32(ycbcr.Y - (0.34414 * (ycbcr.Cb - 128)) - (0.71414 * (ycbcr.Cr - 128))).ToByte();
- byte b = Convert.ToInt32(ycbcr.Y + (1.772 * (ycbcr.Cb - 128))).ToByte();
-
+ float y = ycbcrColor.Y;
+ float cb = ycbcrColor.Cb - 128;
+ float cr = ycbcrColor.Cr - 128;
+
+ byte r = Convert.ToByte(Math.Max(0.0f, Math.Min(255f, y + (1.402 * cr))));
+ byte g = Convert.ToByte(Math.Max(0.0f, Math.Min(255f, y - (0.34414 * cb) - (0.71414 * cr))));
+ byte b = Convert.ToByte(Math.Max(0.0f, Math.Min(255f, y + (1.772 * cb))));
return Color.FromArgb(255, r, g, b);
}
+
+ ///
+ /// Allows the implicit conversion of an instance of to a
+ /// .
+ ///
+ ///
+ /// The instance of to convert.
+ ///
+ ///
+ /// An instance of .
+ ///
+ public static implicit operator RgbaColor(YCbCrColor ycbcrColor)
+ {
+ return RgbaColor.FromColor(ycbcrColor);
+ }
+
+ ///
+ /// Allows the implicit conversion of an instance of to a
+ /// .
+ ///
+ ///
+ /// The instance of to convert.
+ ///
+ ///
+ /// An instance of .
+ ///
+ public static implicit operator HslaColor(YCbCrColor ycbcrColor)
+ {
+ return HslaColor.FromColor(ycbcrColor);
+ }
+
+ ///
+ /// Returns a that represents this instance.
+ ///
+ ///
+ /// A that represents this instance.
+ ///
+ public override string ToString()
+ {
+ if (this.IsEmpty())
+ {
+ return "YCbCrColor [Empty]";
+ }
+
+ return string.Format("YCbCrColor [ Y={0:#0.##}, Cb={1:#0.##}, Cr={2:#0.##}]", this.Y, this.Cb, this.Cr);
+ }
+
+ ///
+ /// Indicates whether this instance and a specified object are equal.
+ ///
+ ///
+ /// true if and this instance are the same type and represent the same value; otherwise, false.
+ ///
+ /// Another object to compare to.
+ public override bool Equals(object obj)
+ {
+ if (obj is YCbCrColor)
+ {
+ Color thisColor = this;
+ Color otherColor = (YCbCrColor)obj;
+
+ return thisColor.Equals(otherColor);
+ }
+
+ return false;
+ }
+
+ ///
+ /// Returns the hash code for this instance.
+ ///
+ ///
+ /// A 32-bit signed integer that is the hash code for this instance.
+ ///
+ public override int GetHashCode()
+ {
+ Color thisColor = this;
+ return thisColor.GetHashCode();
+ }
+
+ ///
+ /// Returns a value indicating whether the current instance is empty.
+ ///
+ ///
+ /// The true if this instance is empty; otherwise, false.
+ ///
+ private bool IsEmpty()
+ {
+ const float Epsilon = .0001f;
+ return Math.Abs(this.y - 0) <= Epsilon && Math.Abs(this.cb - 0) <= Epsilon &&
+ Math.Abs(this.cr - 0) <= Epsilon;
+ }
}
}