diff --git a/src/ImageProcessor.UnitTests/Imaging/ColorUnitTests.cs b/src/ImageProcessor.UnitTests/Imaging/ColorUnitTests.cs
index c522c7f65..70fbfcddb 100644
--- a/src/ImageProcessor.UnitTests/Imaging/ColorUnitTests.cs
+++ b/src/ImageProcessor.UnitTests/Imaging/ColorUnitTests.cs
@@ -10,6 +10,7 @@
namespace ImageProcessor.UnitTests.Imaging
{
+ using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using ImageProcessor.Imaging.Colors;
using NUnit.Framework;
@@ -45,17 +46,78 @@ namespace ImageProcessor.UnitTests.Imaging
}
///
- /// Test conversion to and from a HSLA color.
+ /// Test conversion to and from a .
///
+ ///
+ /// The expected output.
+ ///
[Test]
- public void TestHSLAConversion()
+ [TestCase("#FEFFFE")]
+ [TestCase("#000000")]
+ [TestCase("#CCFF33")]
+ [TestCase("#990000")]
+ [TestCase("#5C955C")]
+ [TestCase("#5C5C95")]
+ [TestCase("#3F3F66")]
+ [TestCase("#FFFFBB")]
+ [TestCase("#FF002B")]
+ [TestCase("#00ABFF")]
+ public void TestHslaConversion(string expected)
{
- const string Hex = "#FEFFFE";
-
- Color color = ColorTranslator.FromHtml(Hex);
+ Color color = ColorTranslator.FromHtml(expected);
HslaColor hslaColor = HslaColor.FromColor(color);
- string outPut = ColorTranslator.ToHtml(hslaColor);
- Assert.AreEqual(Hex, outPut);
+ string result = ColorTranslator.ToHtml(hslaColor);
+ Assert.AreEqual(expected, result);
+ }
+
+ ///
+ /// Test conversion to and from a .
+ ///
+ ///
+ /// The expected output.
+ ///
+ [Test]
+ [TestCase("#FEFFFE")]
+ [TestCase("#000000")]
+ [TestCase("#CCFF33")]
+ [TestCase("#990000")]
+ [TestCase("#5C955C")]
+ [TestCase("#5C5C95")]
+ [TestCase("#3F3F66")]
+ [TestCase("#FFFFBB")]
+ [TestCase("#FF002B")]
+ [TestCase("#00ABFF")]
+ public void TestRgbaConversion(string expected)
+ {
+ Color color = ColorTranslator.FromHtml(expected);
+ RgbaColor rgbaColor = RgbaColor.FromColor(color);
+ string result = ColorTranslator.ToHtml(rgbaColor);
+ 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);
+ //}
}
}
diff --git a/src/ImageProcessor/ImageProcessor.csproj b/src/ImageProcessor/ImageProcessor.csproj
index 50a87b97a..1243ce923 100644
--- a/src/ImageProcessor/ImageProcessor.csproj
+++ b/src/ImageProcessor/ImageProcessor.csproj
@@ -72,6 +72,7 @@
+
diff --git a/src/ImageProcessor/Imaging/Colors/HSLAColor.cs b/src/ImageProcessor/Imaging/Colors/HSLAColor.cs
index 706608f2a..d42ee3a87 100644
--- a/src/ImageProcessor/Imaging/Colors/HSLAColor.cs
+++ b/src/ImageProcessor/Imaging/Colors/HSLAColor.cs
@@ -27,22 +27,22 @@ namespace ImageProcessor.Imaging.Colors
///
/// The hue component.
///
- private readonly double h;
+ private readonly float h;
///
/// The luminosity component.
///
- private readonly double l;
+ private readonly float l;
///
/// The saturation component.
///
- private readonly double s;
+ private readonly float s;
///
/// The alpha component.
///
- private readonly double a;
+ private readonly float a;
///
/// Initializes a new instance of the struct.
@@ -59,7 +59,7 @@ namespace ImageProcessor.Imaging.Colors
///
/// The alpha component.
///
- private HslaColor(double hue, double saturation, double luminosity, double alpha)
+ private HslaColor(float hue, float saturation, float luminosity, float alpha)
{
this.h = Clamp(hue);
this.s = Clamp(saturation);
@@ -85,7 +85,7 @@ namespace ImageProcessor.Imaging.Colors
///
/// Gets the hue component.
///
- public double H
+ public float H
{
get
{
@@ -96,7 +96,7 @@ namespace ImageProcessor.Imaging.Colors
///
/// Gets the luminosity component.
///
- public double L
+ public float L
{
get
{
@@ -107,7 +107,7 @@ namespace ImageProcessor.Imaging.Colors
///
/// Gets the saturation component.
///
- public double S
+ public float S
{
get
{
@@ -118,7 +118,7 @@ namespace ImageProcessor.Imaging.Colors
///
/// Gets the alpha component.
///
- public double A
+ public float A
{
get
{
@@ -127,7 +127,7 @@ namespace ImageProcessor.Imaging.Colors
}
///
- /// Creates a structure from the three 64-bit HSLA
+ /// Creates a structure from the three 32-bit HSLA
/// components (hue, saturation, and luminosity) values.
///
///
@@ -142,13 +142,13 @@ namespace ImageProcessor.Imaging.Colors
///
/// The .
///
- public static HslaColor FromHslaColor(double hue, double saturation, double luminosity)
+ public static HslaColor FromHslaColor(float hue, float saturation, float luminosity)
{
- return new HslaColor(hue, saturation, luminosity, 1.0);
+ return new HslaColor(hue, saturation, luminosity, 1.0f);
}
///
- /// Creates a structure from the four 64-bit HSLA
+ /// Creates a structure from the four 32-bit HSLA
/// components (hue, saturation, luminosity, and alpha) values.
///
///
@@ -166,7 +166,7 @@ namespace ImageProcessor.Imaging.Colors
///
/// The .
///
- public static HslaColor FromHslaColor(double hue, double saturation, double luminosity, double alpha)
+ public static HslaColor FromHslaColor(float hue, float saturation, float luminosity, float alpha)
{
return new HslaColor(hue, saturation, luminosity, alpha);
}
@@ -198,7 +198,7 @@ namespace ImageProcessor.Imaging.Colors
public static implicit operator HslaColor(Color color)
{
HslaColor hslColor = new HslaColor(
- color.GetHue() / 360.0,
+ color.GetHue() / 360.0f,
color.GetSaturation(),
color.GetBrightness(),
color.A / 255f);
@@ -220,7 +220,7 @@ namespace ImageProcessor.Imaging.Colors
{
Color color = rgbaColor;
HslaColor hslColor = new HslaColor(
- color.GetHue() / 360.0,
+ color.GetHue() / 360.0f,
color.GetSaturation(),
color.GetBrightness(),
color.A / 255f);
@@ -240,7 +240,7 @@ namespace ImageProcessor.Imaging.Colors
///
public static implicit operator Color(HslaColor hslaColor)
{
- double r = 0, g = 0, b = 0;
+ float r = 0, g = 0, b = 0;
if (Math.Abs(hslaColor.l - 0) > .0001)
{
if (Math.Abs(hslaColor.s - 0) <= .0001)
@@ -249,12 +249,12 @@ namespace ImageProcessor.Imaging.Colors
}
else
{
- double temp2 = GetTemp2(hslaColor);
- double temp1 = (2.0 * hslaColor.l) - temp2;
+ float temp2 = GetTemp2(hslaColor);
+ float temp1 = (2.0f * hslaColor.l) - temp2;
- r = GetColorComponent(temp1, temp2, hslaColor.h + (1.0 / 3.0));
+ r = GetColorComponent(temp1, temp2, hslaColor.h + (1.0f / 3.0f));
g = GetColorComponent(temp1, temp2, hslaColor.h);
- b = GetColorComponent(temp1, temp2, hslaColor.h - (1.0 / 3.0));
+ b = GetColorComponent(temp1, temp2, hslaColor.h - (1.0f / 3.0f));
}
}
@@ -277,7 +277,7 @@ namespace ImageProcessor.Imaging.Colors
///
public static implicit operator RgbaColor(HslaColor hslaColor)
{
- double r = 0, g = 0, b = 0;
+ float r = 0, g = 0, b = 0;
if (Math.Abs(hslaColor.l - 0) > .0001)
{
if (Math.Abs(hslaColor.s - 0) <= .0001)
@@ -286,12 +286,12 @@ namespace ImageProcessor.Imaging.Colors
}
else
{
- double temp2 = GetTemp2(hslaColor);
- double temp1 = (2.0 * hslaColor.l) - temp2;
+ float temp2 = GetTemp2(hslaColor);
+ float temp1 = (2.0f * hslaColor.l) - temp2;
- r = GetColorComponent(temp1, temp2, hslaColor.h + (1.0 / 3.0));
+ r = GetColorComponent(temp1, temp2, hslaColor.h + (1.0f / 3.0f));
g = GetColorComponent(temp1, temp2, hslaColor.h);
- b = GetColorComponent(temp1, temp2, hslaColor.h - (1.0 / 3.0));
+ b = GetColorComponent(temp1, temp2, hslaColor.h - (1.0f / 3.0f));
}
}
@@ -363,14 +363,14 @@ namespace ImageProcessor.Imaging.Colors
/// The temp 3.
///
///
- /// The .
+ /// The .
///
- private static double GetColorComponent(double temp1, double temp2, double temp3)
+ private static float GetColorComponent(float temp1, float temp2, float temp3)
{
temp3 = MoveIntoRange(temp3);
if (temp3 < 1.0 / 6.0)
{
- return temp1 + ((temp2 - temp1) * 6.0 * temp3);
+ return temp1 + ((temp2 - temp1) * 6.0f * temp3);
}
if (temp3 < 0.5)
@@ -380,7 +380,7 @@ namespace ImageProcessor.Imaging.Colors
if (temp3 < 2.0 / 3.0)
{
- return temp1 + ((temp2 - temp1) * ((2.0 / 3.0) - temp3) * 6.0);
+ return temp1 + ((temp2 - temp1) * ((2.0f / 3.0f) - temp3) * 6.0f);
}
return temp1;
@@ -393,14 +393,14 @@ namespace ImageProcessor.Imaging.Colors
/// The color.
///
///
- /// The .
+ /// The .
///
- private static double GetTemp2(HslaColor hslColor)
+ private static float GetTemp2(HslaColor hslColor)
{
- double temp2;
+ float temp2;
if (hslColor.l <= 0.5)
{
- temp2 = hslColor.l * (1.0 + hslColor.s);
+ temp2 = hslColor.l * (1.0f + hslColor.s);
}
else
{
@@ -417,17 +417,17 @@ namespace ImageProcessor.Imaging.Colors
/// The temp 3.
///
///
- /// The .
+ /// The .
///
- private static double MoveIntoRange(double temp3)
+ private static float MoveIntoRange(float temp3)
{
if (temp3 < 0.0)
{
- temp3 += 1.0;
+ temp3 += 1.0f;
}
else if (temp3 > 1.0)
{
- temp3 -= 1.0;
+ temp3 -= 1.0f;
}
return temp3;
@@ -440,17 +440,17 @@ namespace ImageProcessor.Imaging.Colors
/// The value to check.
///
///
- /// The sanitized .
+ /// The sanitized .
///
- private static double Clamp(double value)
+ private static float Clamp(float value)
{
if (value < 0.0)
{
- value = 0.0;
+ value = 0.0f;
}
else if (value > 1.0)
{
- value = 1.0;
+ value = 1.0f;
}
return value;
@@ -464,7 +464,7 @@ namespace ImageProcessor.Imaging.Colors
///
private bool IsEmpty()
{
- const double Epsilon = .0001;
+ const float Epsilon = .0001f;
return Math.Abs(this.h - 0) <= Epsilon && Math.Abs(this.s - 0) <= Epsilon &&
Math.Abs(this.l - 0) <= Epsilon && Math.Abs(this.a - 0) <= Epsilon;
}
diff --git a/src/ImageProcessor/Imaging/Colors/YCbCrColor.cs b/src/ImageProcessor/Imaging/Colors/YCbCrColor.cs
new file mode 100644
index 000000000..d1a5497c5
--- /dev/null
+++ b/src/ImageProcessor/Imaging/Colors/YCbCrColor.cs
@@ -0,0 +1,163 @@
+// --------------------------------------------------------------------------------------------------------------------
+//
+// Copyright (c) James South.
+// Licensed under the Apache License, Version 2.0.
+//
+//
+// Represents an YCbCr (luminance, chroma, chroma) color used in digital imaging systems.
+//
+//
+// --------------------------------------------------------------------------------------------------------------------
+
+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.
+ ///
+ ///
+ public struct YCbCrColor
+ {
+ ///
+ /// Represents a that is null.
+ ///
+ public static readonly YCbCrColor Empty = new YCbCrColor();
+
+ ///
+ /// The y luminance component.
+ ///
+ private readonly float y;
+
+ ///
+ /// The u chroma component.
+ ///
+ private readonly float cb;
+
+ ///
+ /// The v chroma component.
+ ///
+ private readonly float cr;
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// The y luminance component.
+ /// The u chroma component.
+ /// 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));
+ }
+
+ ///
+ /// Gets the Y luminance component.
+ ///
+ public float Y
+ {
+ get
+ {
+ return this.y;
+ }
+ }
+
+ ///
+ /// Gets the U chroma component.
+ ///
+ public float Cb
+ {
+ get
+ {
+ return this.y;
+ }
+ }
+
+ ///
+ /// Gets the V chroma component.
+ ///
+ public float Cr
+ {
+ get
+ {
+ return this.y;
+ }
+ }
+
+ ///
+ /// Creates a structure from the three 32-bit YCbCr
+ /// components (luminance, chroma, and chroma) values.
+ ///
+ /// The y luminance component.
+ /// The u chroma component.
+ /// The v chroma component.
+ ///
+ /// The .
+ ///
+ public static YCbCrColor FromYCbCr(float y, float cb, float cr)
+ {
+ return new YCbCrColor(y, cb, cr);
+ }
+
+ ///
+ /// Creates a structure from the specified structure
+ ///
+ ///
+ /// The from which to create the new .
+ ///
+ ///
+ /// The .
+ ///
+ public static YCbCrColor FromColor(Color color)
+ {
+ float r = color.R;
+ float g = color.G;
+ float 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 cr = 128 + (float)((0.5 * r) - (0.418688 * g) - (0.081312 * b));
+
+ return new YCbCrColor(y, cb, cr);
+ }
+
+ ///
+ /// Allows the implicit conversion of an instance of to a
+ /// .
+ ///
+ ///
+ /// The instance of to convert.
+ ///
+ ///
+ /// An instance of .
+ ///
+ public static implicit operator YCbCrColor(Color color)
+ {
+ 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 Color(YCbCrColor ycbcr)
+ {
+ 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();
+
+
+ return Color.FromArgb(255, r, g, b);
+ }
+ }
+}
diff --git a/src/ImageProcessor/Processors/Hue.cs b/src/ImageProcessor/Processors/Hue.cs
index 0ddc7b98d..2c59dcc54 100644
--- a/src/ImageProcessor/Processors/Hue.cs
+++ b/src/ImageProcessor/Processors/Hue.cs
@@ -70,7 +70,7 @@ namespace ImageProcessor.Processors
for (int j = 0; j < height; j++)
{
HslaColor original = HslaColor.FromColor(fastBitmap.GetPixel(i, j));
- HslaColor altered = HslaColor.FromHslaColor(degrees / 360D, original.S, original.L, original.A);
+ HslaColor altered = HslaColor.FromHslaColor(degrees / 360f, original.S, original.L, original.A);
fastBitmap.SetPixel(i, j, altered);
}
}