diff --git a/src/ImageProcessor.UnitTests/Imaging/ColorUnitTests.cs b/src/ImageProcessor.UnitTests/Imaging/ColorUnitTests.cs
index 512b93d6e..c522c7f65 100644
--- a/src/ImageProcessor.UnitTests/Imaging/ColorUnitTests.cs
+++ b/src/ImageProcessor.UnitTests/Imaging/ColorUnitTests.cs
@@ -21,25 +21,25 @@ namespace ImageProcessor.UnitTests.Imaging
public class ColorUnitTests
{
///
- /// Tests the struct equality operators.
+ /// Tests the struct equality operators.
///
[Test]
public void TestRGBAEquality()
{
- RGBAColor first = new RGBAColor(Color.White);
- RGBAColor second = new RGBAColor(Color.White);
+ RgbaColor first = RgbaColor.FromColor(Color.White);
+ RgbaColor second = RgbaColor.FromColor(Color.White);
Assert.AreEqual(first, second);
}
///
- /// Tests the struct equality operators.
+ /// Tests the struct equality operators.
///
[Test]
public void TestHSLAEquality()
{
- HSLAColor first = new HSLAColor(Color.White);
- HSLAColor second = new HSLAColor(Color.White);
+ HslaColor first = HslaColor.FromColor(Color.White);
+ HslaColor second = HslaColor.FromColor(Color.White);
Assert.AreEqual(first, second);
}
@@ -53,7 +53,7 @@ namespace ImageProcessor.UnitTests.Imaging
const string Hex = "#FEFFFE";
Color color = ColorTranslator.FromHtml(Hex);
- HSLAColor hslaColor = new HSLAColor(color);
+ HslaColor hslaColor = HslaColor.FromColor(color);
string outPut = ColorTranslator.ToHtml(hslaColor);
Assert.AreEqual(Hex, outPut);
}
diff --git a/src/ImageProcessor/ImageProcessor.csproj b/src/ImageProcessor/ImageProcessor.csproj
index 7c028707d..50a87b97a 100644
--- a/src/ImageProcessor/ImageProcessor.csproj
+++ b/src/ImageProcessor/ImageProcessor.csproj
@@ -70,8 +70,8 @@
-
-
+
+
diff --git a/src/ImageProcessor/Imaging/Colors/HSLAColor.cs b/src/ImageProcessor/Imaging/Colors/HSLAColor.cs
index 19c12e54a..706608f2a 100644
--- a/src/ImageProcessor/Imaging/Colors/HSLAColor.cs
+++ b/src/ImageProcessor/Imaging/Colors/HSLAColor.cs
@@ -14,61 +14,68 @@ namespace ImageProcessor.Imaging.Colors
/// Represents an HSLA (hue, saturation, luminosity, alpha) color.
/// Adapted from
///
- public struct HSLAColor
+ public struct HslaColor
{
+ ///
+ /// Represents a that is null.
+ ///
+ public static readonly HslaColor Empty = new HslaColor();
+
// Private data members below are on scale 0-1
// They are scaled for use externally based on scale
///
/// The hue component.
///
- private double h;
+ private readonly double h;
///
/// The luminosity component.
///
- private double l;
+ private readonly double l;
///
/// The saturation component.
///
- private double s;
+ private readonly double s;
///
/// The alpha component.
///
- private double a;
+ private readonly double a;
///
- /// Initializes a new instance of the struct.
+ /// Initializes a new instance of the struct.
///
///
- /// The hue.
+ /// The hue component.
///
///
- /// The saturation.
+ /// The saturation component.
///
///
- /// The luminosity.
+ /// The luminosity component.
///
- public HSLAColor(double hue, double saturation, double luminosity)
- : this()
+ ///
+ /// The alpha component.
+ ///
+ private HslaColor(double hue, double saturation, double luminosity, double alpha)
{
- this.H = hue;
- this.S = saturation;
- this.L = luminosity;
+ this.h = Clamp(hue);
+ this.s = Clamp(saturation);
+ this.l = Clamp(luminosity);
+ this.a = Clamp(alpha);
}
///
- /// Initializes a new instance of the struct.
+ /// Initializes a new instance of the struct.
///
///
/// The to initialize from.
///
- public HSLAColor(Color color)
- : this()
+ private HslaColor(Color color)
{
- HSLAColor hslColor = color;
+ HslaColor hslColor = color;
this.h = hslColor.h;
this.s = hslColor.s;
this.l = hslColor.l;
@@ -76,7 +83,7 @@ namespace ImageProcessor.Imaging.Colors
}
///
- /// Gets or sets the hue component.
+ /// Gets the hue component.
///
public double H
{
@@ -84,15 +91,10 @@ namespace ImageProcessor.Imaging.Colors
{
return this.h;
}
-
- set
- {
- this.h = this.CheckRange(value);
- }
}
///
- /// Gets or sets the luminosity component.
+ /// Gets the luminosity component.
///
public double L
{
@@ -100,15 +102,10 @@ namespace ImageProcessor.Imaging.Colors
{
return this.l;
}
-
- set
- {
- this.l = this.CheckRange(value);
- }
}
///
- /// Gets or sets the saturation component.
+ /// Gets the saturation component.
///
public double S
{
@@ -116,15 +113,10 @@ namespace ImageProcessor.Imaging.Colors
{
return this.s;
}
-
- set
- {
- this.s = this.CheckRange(value);
- }
}
///
- /// Gets or sets the alpha component.
+ /// Gets the alpha component.
///
public double A
{
@@ -132,71 +124,121 @@ namespace ImageProcessor.Imaging.Colors
{
return this.a;
}
+ }
- set
- {
- this.a = this.CheckRange(value);
- }
+ ///
+ /// Creates a structure from the three 64-bit HSLA
+ /// components (hue, saturation, and luminosity) values.
+ ///
+ ///
+ /// The hue component.
+ ///
+ ///
+ /// The saturation component.
+ ///
+ ///
+ /// The luminosity component.
+ ///
+ ///
+ /// The .
+ ///
+ public static HslaColor FromHslaColor(double hue, double saturation, double luminosity)
+ {
+ return new HslaColor(hue, saturation, luminosity, 1.0);
+ }
+
+ ///
+ /// Creates a structure from the four 64-bit HSLA
+ /// components (hue, saturation, luminosity, and alpha) values.
+ ///
+ ///
+ /// The hue component.
+ ///
+ ///
+ /// The saturation component.
+ ///
+ ///
+ /// The luminosity component.
+ ///
+ ///
+ /// The alpha component.
+ ///
+ ///
+ /// The .
+ ///
+ public static HslaColor FromHslaColor(double hue, double saturation, double luminosity, double alpha)
+ {
+ return new HslaColor(hue, saturation, luminosity, alpha);
+ }
+
+ ///
+ /// Creates a structure from the specified structure
+ ///
+ ///
+ /// The from which to create the new .
+ ///
+ ///
+ /// The .
+ ///
+ public static HslaColor FromColor(Color color)
+ {
+ return new HslaColor(color);
}
///
/// Allows the implicit conversion of an instance of to a
- /// .
+ /// .
///
///
/// The instance of to convert.
///
///
- /// An instance of .
+ /// An instance of .
///
- public static implicit operator HSLAColor(Color color)
+ public static implicit operator HslaColor(Color color)
{
- HSLAColor hslColor = new HSLAColor
- {
- h = color.GetHue() / 360.0,
- l = color.GetBrightness(),
- s = color.GetSaturation(),
- a = color.A / 255f
- };
+ HslaColor hslColor = new HslaColor(
+ color.GetHue() / 360.0,
+ color.GetSaturation(),
+ color.GetBrightness(),
+ color.A / 255f);
return hslColor;
}
///
/// Allows the implicit conversion of an instance of to a
- /// .
+ /// .
///
///
- /// The instance of to convert.
+ /// The instance of to convert.
///
///
- /// An instance of .
+ /// An instance of .
///
- public static implicit operator HSLAColor(RGBAColor rgbaColor)
+ public static implicit operator HslaColor(RgbaColor rgbaColor)
{
Color color = rgbaColor;
- HSLAColor hslColor = new HSLAColor
- {
- h = color.GetHue() / 360.0,
- l = color.GetBrightness(),
- s = color.GetSaturation(),
- a = color.A / 255f
- };
+ HslaColor hslColor = new HslaColor(
+ color.GetHue() / 360.0,
+ color.GetSaturation(),
+ color.GetBrightness(),
+ color.A / 255f);
return hslColor;
}
///
- /// 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 Color(HSLAColor hslaColor)
+ public static implicit operator Color(HslaColor hslaColor)
{
double r = 0, g = 0, b = 0;
if (Math.Abs(hslaColor.l - 0) > .0001)
@@ -216,20 +258,24 @@ namespace ImageProcessor.Imaging.Colors
}
}
- return Color.FromArgb(Convert.ToInt32(255 * hslaColor.a), Convert.ToInt32(255 * r), Convert.ToInt32(255 * g), Convert.ToInt32(255 * b));
+ return Color.FromArgb(
+ Convert.ToInt32(255 * hslaColor.a),
+ Convert.ToInt32(255 * r),
+ Convert.ToInt32(255 * g),
+ Convert.ToInt32(255 * b));
}
///
- /// 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 .
+ /// An instance of .
///
- public static implicit operator RGBAColor(HSLAColor hslaColor)
+ public static implicit operator RgbaColor(HslaColor hslaColor)
{
double r = 0, g = 0, b = 0;
if (Math.Abs(hslaColor.l - 0) > .0001)
@@ -249,19 +295,11 @@ namespace ImageProcessor.Imaging.Colors
}
}
- return new RGBAColor(Convert.ToByte(255 * r), Convert.ToByte(255 * g), Convert.ToByte(255 * b), Convert.ToByte(255 * hslaColor.a));
- }
-
- ///
- /// Returns a that represents this instance.
- ///
- ///
- /// A that represents this instance.
- ///
- public string ToRGBAString()
- {
- Color color = this;
- return string.Format("R={0}, G={1}, B={2}, A={3}", color.R, color.G, color.B, color.A);
+ return RgbaColor.FromRgba(
+ Convert.ToByte(255 * r),
+ Convert.ToByte(255 * g),
+ Convert.ToByte(255 * b),
+ Convert.ToByte(255 * hslaColor.a));
}
///
@@ -272,7 +310,12 @@ namespace ImageProcessor.Imaging.Colors
///
public override string ToString()
{
- return string.Format("H={0:#0.##}, S={1:#0.##}, L={2:#0.##}, A={3:#0.##}", this.H, this.S, this.L, this.A);
+ if (this.IsEmpty())
+ {
+ return "HSLAColor [Empty]";
+ }
+
+ return string.Format("HSLAColor [ H={0:#0.##}, S={1:#0.##}, L={2:#0.##}, A={3:#0.##}]", this.H, this.S, this.L, this.A);
}
///
@@ -284,10 +327,10 @@ namespace ImageProcessor.Imaging.Colors
/// Another object to compare to.
public override bool Equals(object obj)
{
- if (obj is HSLAColor)
+ if (obj is HslaColor)
{
Color thisColor = this;
- Color otherColor = (HSLAColor)obj;
+ Color otherColor = (HslaColor)obj;
return thisColor.Equals(otherColor);
}
@@ -347,12 +390,12 @@ namespace ImageProcessor.Imaging.Colors
/// The get temp 2.
///
///
- /// The color.
+ /// The color.
///
///
/// The .
///
- private static double GetTemp2(HSLAColor hslColor)
+ private static double GetTemp2(HslaColor hslColor)
{
double temp2;
if (hslColor.l <= 0.5)
@@ -399,7 +442,7 @@ namespace ImageProcessor.Imaging.Colors
///
/// The sanitized .
///
- private double CheckRange(double value)
+ private static double Clamp(double value)
{
if (value < 0.0)
{
@@ -412,5 +455,18 @@ namespace ImageProcessor.Imaging.Colors
return value;
}
+
+ ///
+ /// Returns a value indicating whether the current instance is empty.
+ ///
+ ///
+ /// The true if this instance is empty; otherwise, false.
+ ///
+ private bool IsEmpty()
+ {
+ const double Epsilon = .0001;
+ 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;
+ }
}
}
\ No newline at end of file
diff --git a/src/ImageProcessor/Imaging/Colors/RGBAColor.cs b/src/ImageProcessor/Imaging/Colors/RGBAColor.cs
index a9127fae7..38976154a 100644
--- a/src/ImageProcessor/Imaging/Colors/RGBAColor.cs
+++ b/src/ImageProcessor/Imaging/Colors/RGBAColor.cs
@@ -1,5 +1,5 @@
// --------------------------------------------------------------------------------------------------------------------
-//
+//
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
//
@@ -8,35 +8,121 @@
namespace ImageProcessor.Imaging.Colors
{
using System.Drawing;
- using System.Text;
///
/// Represents an RGBA (red, green, blue, alpha) color.
///
- public struct RGBAColor
+ public struct RgbaColor
{
///
- /// The alpha component.
+ /// Represents a that is null.
///
- public byte A;
+ public static readonly RgbaColor Empty = new RgbaColor();
///
- /// The blue component.
+ /// The red component.
///
- public byte B;
+ private readonly byte r;
///
/// The green component.
///
- public byte G;
+ private readonly byte g;
+
+ ///
+ /// The blue component.
+ ///
+ private readonly byte b;
+
+ ///
+ /// The alpha component.
+ ///
+ private readonly byte a;
///
+ /// Initializes a new instance of the struct.
+ ///
+ ///
/// The red component.
+ ///
+ ///
+ /// The green component.
+ ///
+ ///
+ /// The blue component.
+ ///
+ ///
+ /// The alpha component.
+ ///
+ private RgbaColor(byte red, byte green, byte blue, byte alpha)
+ {
+ this.r = red;
+ this.g = green;
+ this.b = blue;
+ this.a = alpha;
+ }
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ ///
+ /// The color.
+ ///
+ private RgbaColor(Color color)
+ {
+ this.r = color.R;
+ this.g = color.G;
+ this.b = color.B;
+ this.a = color.A;
+ }
+
+ ///
+ /// Gets the red component.
///
- public byte R;
+ public byte R
+ {
+ get
+ {
+ return this.r;
+ }
+ }
+
+ ///
+ /// Gets the green component.
+ ///
+ public byte G
+ {
+ get
+ {
+ return this.g;
+ }
+ }
+
+ ///
+ /// Gets the blue component.
+ ///
+ public byte B
+ {
+ get
+ {
+ return this.b;
+ }
+ }
///
- /// Initializes a new instance of the struct.
+ /// Gets the alpha component.
+ ///
+ public byte A
+ {
+ get
+ {
+ return this.a;
+ }
+ }
+
+ ///
+ /// Creates a structure from the three 8-bit RGBA
+ /// components (red, green, and blue) values.
///
///
/// The red component.
@@ -47,16 +133,17 @@ namespace ImageProcessor.Imaging.Colors
///
/// The blue component.
///
- public RGBAColor(byte red, byte green, byte blue)
+ ///
+ /// The .
+ ///
+ public static RgbaColor FromRgba(byte red, byte green, byte blue)
{
- this.R = red;
- this.G = green;
- this.B = blue;
- this.A = 255;
+ return new RgbaColor(red, green, blue, 255);
}
///
- /// Initializes a new instance of the struct.
+ /// Creates a structure from the four 8-bit RGBA
+ /// components (red, green, blue, and alpha) values.
///
///
/// The red component.
@@ -70,86 +157,86 @@ namespace ImageProcessor.Imaging.Colors
///
/// The alpha component.
///
- public RGBAColor(byte red, byte green, byte blue, byte alpha)
+ ///
+ /// The .
+ ///
+ public static RgbaColor FromRgba(byte red, byte green, byte blue, byte alpha)
{
- this.R = red;
- this.G = green;
- this.B = blue;
- this.A = alpha;
+ return new RgbaColor(red, green, blue, alpha);
}
///
- /// Initializes a new instance of the struct.
+ /// Creates a structure from the specified structure
///
///
- /// The color.
+ /// The from which to create the new .
///
- public RGBAColor(Color color)
+ ///
+ /// The .
+ ///
+ public static RgbaColor FromColor(Color color)
{
- this.R = color.R;
- this.G = color.G;
- this.B = color.B;
- this.A = color.A;
+ return new RgbaColor(color);
}
///
/// Allows the implicit conversion of an instance of to a
- /// .
+ /// .
///
///
/// The instance of to convert.
///
///
- /// An instance of .
+ /// An instance of .
///
- public static implicit operator RGBAColor(Color color)
+ public static implicit operator RgbaColor(Color color)
{
- return new RGBAColor(color);
+ return new RgbaColor(color);
}
///
/// Allows the implicit conversion of an instance of to a
- /// .
+ /// .
///
///
/// The instance of to convert.
///
///
- /// An instance of .
+ /// An instance of .
///
- public static implicit operator RGBAColor(HSLAColor color)
+ public static implicit operator RgbaColor(HslaColor color)
{
- return new RGBAColor(color);
+ return new RgbaColor(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 Color(RGBAColor rgba)
+ public static implicit operator Color(RgbaColor rgba)
{
return Color.FromArgb(rgba.A, rgba.R, rgba.G, rgba.B);
}
///
- /// 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 .
+ /// An instance of .
///
- public static implicit operator HSLAColor(RGBAColor rgba)
+ public static implicit operator HslaColor(RgbaColor rgba)
{
- return new HSLAColor(rgba);
+ return HslaColor.FromColor(rgba);
}
///
@@ -160,7 +247,12 @@ namespace ImageProcessor.Imaging.Colors
///
public override string ToString()
{
- return string.Format("R={0}, G={1}, B={2}, A={3}", this.R, this.G, this.B, this.A);
+ if (this.R == 0 && this.G == 0 && this.B == 0 && this.A == 0)
+ {
+ return "RGBA [Empty]";
+ }
+
+ return string.Format("RGBA [R={0}, G={1}, B={2}, A={3}]", this.R, this.G, this.B, this.A);
}
///
@@ -172,10 +264,10 @@ namespace ImageProcessor.Imaging.Colors
/// Another object to compare to.
public override bool Equals(object obj)
{
- if (obj is RGBAColor)
+ if (obj is RgbaColor)
{
Color thisColor = this;
- Color otherColor = (RGBAColor)obj;
+ Color otherColor = (RgbaColor)obj;
return thisColor.Equals(otherColor);
}
diff --git a/src/ImageProcessor/Processors/Hue.cs b/src/ImageProcessor/Processors/Hue.cs
index d13b1217f..0ddc7b98d 100644
--- a/src/ImageProcessor/Processors/Hue.cs
+++ b/src/ImageProcessor/Processors/Hue.cs
@@ -69,8 +69,9 @@ namespace ImageProcessor.Processors
{
for (int j = 0; j < height; j++)
{
- HSLAColor hsla = new HSLAColor(fastBitmap.GetPixel(i, j)) { H = degrees / 360f };
- fastBitmap.SetPixel(i, j, hsla);
+ HslaColor original = HslaColor.FromColor(fastBitmap.GetPixel(i, j));
+ HslaColor altered = HslaColor.FromHslaColor(degrees / 360D, original.S, original.L, original.A);
+ fastBitmap.SetPixel(i, j, altered);
}
}
}
diff --git a/src/ImageProcessor/Processors/HueRotate.cs b/src/ImageProcessor/Processors/HueRotate.cs
index 975b681c6..9d99af892 100644
--- a/src/ImageProcessor/Processors/HueRotate.cs
+++ b/src/ImageProcessor/Processors/HueRotate.cs
@@ -69,9 +69,9 @@ namespace ImageProcessor.Processors
{
for (int j = 0; j < height; j++)
{
- HSLAColor hsla = new HSLAColor(fastBitmap.GetPixel(i, j));
- hsla.H = (hsla.H + (degrees / 360f)) % 1;
- fastBitmap.SetPixel(i, j, hsla);
+ HslaColor original = HslaColor.FromColor(fastBitmap.GetPixel(i, j));
+ HslaColor altered = HslaColor.FromHslaColor((original.H + (degrees / 360f)) % 1, original.S, original.L, original.A);
+ fastBitmap.SetPixel(i, j, altered);
}
}
}
diff --git a/src/ImageProcessorConsole/Program.cs b/src/ImageProcessorConsole/Program.cs
index 169eecd9e..5b605dfca 100644
--- a/src/ImageProcessorConsole/Program.cs
+++ b/src/ImageProcessorConsole/Program.cs
@@ -50,16 +50,7 @@ namespace ImageProcessorConsole
foreach (FileInfo fileInfo in files)
{
byte[] photoBytes = File.ReadAllBytes(fileInfo.FullName);
-
- //Color color = Color.Green;
- //HSLAColor hslaColor = HSLAColor.FromRGBA(color);
- //Console.WriteLine("H:" + hslaColor.H + " S:" + hslaColor.S + " L:" + hslaColor.L);
-
- //Color color2 = HSLAColor.ToRGBA(hslaColor);
-
- //Console.WriteLine("Color Out: " + "R:" + color2.R + " G:" + color2.G + " B:" + color2.B + " A:" + color2.A);
- //Console.WriteLine(color2 == Color.Green);
- //Console.WriteLine("Processing: " + fileInfo.Name);
+ Console.WriteLine("Processing: " + fileInfo.Name);
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
@@ -82,7 +73,7 @@ namespace ImageProcessorConsole
//.Resize(new Size((int)(size.Width * 1.1), 0))
//.ContentAwareResize(layer)
.Constrain(size)
- .HueRotate(270)
+ .Hue(180)
.Quality(100)
.Save(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(path), @"..\..\images\output", fileInfo.Name)));