Browse Source

Adding Hue and HueRotate

Former-commit-id: 654fd398b5ff802c2ad23f0eea38773337dc8ceb
pull/17/head
James South 12 years ago
parent
commit
42ae3a047b
  1. 37
      src/ImageProcessor.UnitTests/ImageFactoryUnitTests.cs
  2. 1
      src/ImageProcessor.UnitTests/ImageProcessor.UnitTests.csproj
  3. 61
      src/ImageProcessor.UnitTests/Imaging/ColorUnitTests.cs
  4. 31
      src/ImageProcessor/ImageFactory.cs
  5. 1
      src/ImageProcessor/ImageProcessor.csproj
  6. 291
      src/ImageProcessor/Imaging/Colors/HSLAColor.cs
  7. 91
      src/ImageProcessor/Imaging/Colors/RGBAColor.cs
  8. 8
      src/ImageProcessor/Processors/Hue.cs
  9. 95
      src/ImageProcessor/Processors/HueRotate.cs
  10. 3
      src/ImageProcessorConsole/Program.cs
  11. BIN
      src/ImageProcessorConsole/images/output/1aaa.jpg
  12. BIN
      src/ImageProcessorConsole/images/output/2006-citybus.jpg
  13. 1
      src/ImageProcessorConsole/images/output/2008.jpg.REMOVED.git-id
  14. BIN
      src/ImageProcessorConsole/images/output/2012-citybus.jpg
  15. 1
      src/ImageProcessorConsole/images/output/Arc-de-Triomphe-France.jpg.REMOVED.git-id
  16. BIN
      src/ImageProcessorConsole/images/output/IC580196.jpg
  17. BIN
      src/ImageProcessorConsole/images/output/Turtle.jpg
  18. BIN
      src/ImageProcessorConsole/images/output/arc_de_triomphe_paris_france.jpg
  19. BIN
      src/ImageProcessorConsole/images/output/mountain.jpg
  20. BIN
      src/ImageProcessorConsole/images/output/rotate.jpg
  21. BIN
      src/ImageProcessorConsole/images/output/sample1.jpg
  22. BIN
      src/ImageProcessorConsole/images/output/shutterstock_19173982_Arc_de_triomphe-square1.jpg
  23. BIN
      src/ImageProcessorConsole/images/output/test.jpg
  24. BIN
      src/ImageProcessorConsole/images/output/tower.jpg

37
src/ImageProcessor.UnitTests/ImageFactoryUnitTests.cs

@ -15,6 +15,9 @@ namespace ImageProcessor.UnitTests
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using ImageProcessor.Imaging;
using NUnit.Framework; using NUnit.Framework;
/// <summary> /// <summary>
@ -244,7 +247,7 @@ namespace ImageProcessor.UnitTests
{ {
imageFactory.Load(file.FullName); imageFactory.Load(file.FullName);
Image original = (Image)imageFactory.Image.Clone(); Image original = (Image)imageFactory.Image.Clone();
imageFactory.Watermark(new Imaging.TextLayer imageFactory.Watermark(new TextLayer
{ {
FontFamily = new FontFamily("Arial"), FontFamily = new FontFamily("Arial"),
FontSize = 10, FontSize = 10,
@ -286,7 +289,7 @@ namespace ImageProcessor.UnitTests
{ {
imageFactory.Load(file.FullName); imageFactory.Load(file.FullName);
Image original = (Image)imageFactory.Image.Clone(); Image original = (Image)imageFactory.Image.Clone();
imageFactory.GaussianBlur(new Imaging.GaussianLayer { Sigma = 10, Size = 5, Threshold = 2 }); imageFactory.GaussianBlur(new GaussianLayer { Sigma = 10, Size = 5, Threshold = 2 });
Assert.AreNotEqual(original, imageFactory.Image); Assert.AreNotEqual(original, imageFactory.Image);
} }
} }
@ -322,7 +325,7 @@ namespace ImageProcessor.UnitTests
{ {
imageFactory.Load(file.FullName); imageFactory.Load(file.FullName);
Image original = (Image)imageFactory.Image.Clone(); Image original = (Image)imageFactory.Image.Clone();
imageFactory.GaussianSharpen(new Imaging.GaussianLayer { Sigma = 10, Size = 5, Threshold = 2 }); imageFactory.GaussianSharpen(new GaussianLayer { Sigma = 10, Size = 5, Threshold = 2 });
Assert.AreNotEqual(original, imageFactory.Image); Assert.AreNotEqual(original, imageFactory.Image);
} }
} }
@ -341,43 +344,43 @@ namespace ImageProcessor.UnitTests
imageFactory.Load(file.FullName); imageFactory.Load(file.FullName);
Image original = (Image)imageFactory.Image.Clone(); Image original = (Image)imageFactory.Image.Clone();
imageFactory.Filter(Imaging.Filters.MatrixFilters.BlackWhite); imageFactory.Filter(ImageProcessor.Imaging.Filters.MatrixFilters.BlackWhite);
Assert.AreNotEqual(original, imageFactory.Image); Assert.AreNotEqual(original, imageFactory.Image);
imageFactory.Reset(); imageFactory.Reset();
imageFactory.Filter(Imaging.Filters.MatrixFilters.Comic); imageFactory.Filter(ImageProcessor.Imaging.Filters.MatrixFilters.Comic);
Assert.AreNotEqual(original, imageFactory.Image); Assert.AreNotEqual(original, imageFactory.Image);
imageFactory.Reset(); imageFactory.Reset();
imageFactory.Filter(Imaging.Filters.MatrixFilters.Gotham); imageFactory.Filter(ImageProcessor.Imaging.Filters.MatrixFilters.Gotham);
Assert.AreNotEqual(original, imageFactory.Image); Assert.AreNotEqual(original, imageFactory.Image);
imageFactory.Reset(); imageFactory.Reset();
imageFactory.Filter(Imaging.Filters.MatrixFilters.GreyScale); imageFactory.Filter(ImageProcessor.Imaging.Filters.MatrixFilters.GreyScale);
Assert.AreNotEqual(original, imageFactory.Image); Assert.AreNotEqual(original, imageFactory.Image);
imageFactory.Reset(); imageFactory.Reset();
imageFactory.Filter(Imaging.Filters.MatrixFilters.HiSatch); imageFactory.Filter(ImageProcessor.Imaging.Filters.MatrixFilters.HiSatch);
Assert.AreNotEqual(original, imageFactory.Image); Assert.AreNotEqual(original, imageFactory.Image);
imageFactory.Reset(); imageFactory.Reset();
imageFactory.Filter(Imaging.Filters.MatrixFilters.Invert); imageFactory.Filter(ImageProcessor.Imaging.Filters.MatrixFilters.Invert);
Assert.AreNotEqual(original, imageFactory.Image); Assert.AreNotEqual(original, imageFactory.Image);
imageFactory.Reset(); imageFactory.Reset();
imageFactory.Filter(Imaging.Filters.MatrixFilters.Lomograph); imageFactory.Filter(ImageProcessor.Imaging.Filters.MatrixFilters.Lomograph);
Assert.AreNotEqual(original, imageFactory.Image); Assert.AreNotEqual(original, imageFactory.Image);
imageFactory.Reset(); imageFactory.Reset();
imageFactory.Filter(Imaging.Filters.MatrixFilters.LoSatch); imageFactory.Filter(ImageProcessor.Imaging.Filters.MatrixFilters.LoSatch);
Assert.AreNotEqual(original, imageFactory.Image); Assert.AreNotEqual(original, imageFactory.Image);
imageFactory.Reset(); imageFactory.Reset();
imageFactory.Filter(Imaging.Filters.MatrixFilters.Polaroid); imageFactory.Filter(ImageProcessor.Imaging.Filters.MatrixFilters.Polaroid);
Assert.AreNotEqual(original, imageFactory.Image); Assert.AreNotEqual(original, imageFactory.Image);
imageFactory.Reset(); imageFactory.Reset();
imageFactory.Filter(Imaging.Filters.MatrixFilters.Sepia); imageFactory.Filter(ImageProcessor.Imaging.Filters.MatrixFilters.Sepia);
Assert.AreNotEqual(original, imageFactory.Image); Assert.AreNotEqual(original, imageFactory.Image);
imageFactory.Reset(); imageFactory.Reset();
} }
@ -396,7 +399,7 @@ namespace ImageProcessor.UnitTests
{ {
imageFactory.Load(file.FullName); imageFactory.Load(file.FullName);
Image original = (Image)imageFactory.Image.Clone(); Image original = (Image)imageFactory.Image.Clone();
imageFactory.RoundedCorners(new Imaging.RoundedCornerLayer(5)); imageFactory.RoundedCorners(new RoundedCornerLayer(5));
Assert.AreNotEqual(original, imageFactory.Image); Assert.AreNotEqual(original, imageFactory.Image);
} }
} }
@ -455,7 +458,7 @@ namespace ImageProcessor.UnitTests
{ {
imageFactory.Load(file.FullName); imageFactory.Load(file.FullName);
Image original = (Image)imageFactory.Image.Clone(); Image original = (Image)imageFactory.Image.Clone();
imageFactory.Crop(new Imaging.CropLayer(0, 0, MaxSize, MaxSize, Imaging.CropMode.Pixels)); imageFactory.Crop(new CropLayer(0, 0, MaxSize, MaxSize, CropMode.Pixels));
Assert.AreNotEqual(original, imageFactory.Image); Assert.AreNotEqual(original, imageFactory.Image);
Assert.AreEqual(MaxSize, imageFactory.Image.Width); Assert.AreEqual(MaxSize, imageFactory.Image.Width);
Assert.LessOrEqual(MaxSize, imageFactory.Image.Height); Assert.LessOrEqual(MaxSize, imageFactory.Image.Height);
@ -481,7 +484,7 @@ namespace ImageProcessor.UnitTests
Assert.AreEqual(original.Height, imageFactory.Image.Height); Assert.AreEqual(original.Height, imageFactory.Image.Height);
imageFactory.Reset(); imageFactory.Reset();
imageFactory.Flip(false); imageFactory.Flip();
Assert.AreNotEqual(original, imageFactory.Image); Assert.AreNotEqual(original, imageFactory.Image);
Assert.AreEqual(original.Width, imageFactory.Image.Width); Assert.AreEqual(original.Width, imageFactory.Image.Width);
Assert.AreEqual(original.Height, imageFactory.Image.Height); Assert.AreEqual(original.Height, imageFactory.Image.Height);
@ -520,7 +523,7 @@ namespace ImageProcessor.UnitTests
using (ImageFactory imageFactory = new ImageFactory()) using (ImageFactory imageFactory = new ImageFactory())
{ {
imageFactory.Load(file.FullName); imageFactory.Load(file.FullName);
imageFactory.Resize(new Imaging.ResizeLayer(new Size(NewSize, NewSize), Imaging.ResizeMode.Stretch, Imaging.AnchorPosition.Left)); imageFactory.Resize(new ResizeLayer(new Size(NewSize, NewSize), ResizeMode.Stretch, AnchorPosition.Left));
Assert.AreEqual(NewSize, imageFactory.Image.Width); Assert.AreEqual(NewSize, imageFactory.Image.Width);
Assert.AreEqual(NewSize, imageFactory.Image.Height); Assert.AreEqual(NewSize, imageFactory.Image.Height);
} }

1
src/ImageProcessor.UnitTests/ImageProcessor.UnitTests.csproj

@ -51,6 +51,7 @@
</Compile> </Compile>
<Compile Include="Extensions\DoubleExtensionsUnitTests.cs" /> <Compile Include="Extensions\DoubleExtensionsUnitTests.cs" />
<Compile Include="Extensions\IntegerExtensionsUnitTests.cs" /> <Compile Include="Extensions\IntegerExtensionsUnitTests.cs" />
<Compile Include="Imaging\ColorUnitTests.cs" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup> <ItemGroup>

61
src/ImageProcessor.UnitTests/Imaging/ColorUnitTests.cs

@ -0,0 +1,61 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ColorUnitTests.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// Test harness for the color classes.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.UnitTests.Imaging
{
using System.Drawing;
using ImageProcessor.Imaging.Colors;
using NUnit.Framework;
/// <summary>
/// Test harness for the color classes.
/// </summary>
[TestFixture]
public class ColorUnitTests
{
/// <summary>
/// Tests the <see cref="RGBAColor"/> struct equality operators.
/// </summary>
[Test]
public void TestRGBAEquality()
{
RGBAColor first = new RGBAColor(Color.White);
RGBAColor second = new RGBAColor(Color.White);
Assert.AreEqual(first, second);
}
/// <summary>
/// Tests the <see cref="RGBAColor"/> struct equality operators.
/// </summary>
[Test]
public void TestHSLAEquality()
{
HSLAColor first = new HSLAColor(Color.White);
HSLAColor second = new HSLAColor(Color.White);
Assert.AreEqual(first, second);
}
/// <summary>
/// Test conversion to and from a HSLA color.
/// </summary>
[Test]
public void TestHSLAConversion()
{
const string Hex = "#FEFFFE";
Color color = ColorTranslator.FromHtml(Hex);
HSLAColor hslaColor = new HSLAColor(color);
string outPut = ColorTranslator.ToHtml(hslaColor);
Assert.AreEqual(Hex, outPut);
}
}
}

31
src/ImageProcessor/ImageFactory.cs

@ -597,11 +597,11 @@ namespace ImageProcessor
} }
/// <summary> /// <summary>
/// Changes the hue of the current image. /// Alters the hue of the current image changing the overall color.
/// </summary> /// </summary>
/// <param name="degrees"> /// <param name="degrees">
/// The angle by which to alter the images hue. /// The angle by which to alter the images hue.
/// Any integer between 0 and 359. /// Any integer between 0 and 360.
/// </param> /// </param>
/// <returns> /// <returns>
/// The current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class. /// The current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class.
@ -623,6 +623,33 @@ namespace ImageProcessor
return this; return this;
} }
/// <summary>
/// Rotates the hue of the current image altering each color.
/// </summary>
/// <param name="degrees">
/// The angle by which to rotate the images hue.
/// Any integer between 0 and 360.
/// </param>
/// <returns>
/// The current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class.
/// </returns>
public ImageFactory HueRotate(int degrees)
{
// Sanitize the input.
if (degrees > 360 || degrees < 0)
{
degrees = 0;
}
if (this.ShouldProcess)
{
HueRotate hue = new HueRotate { DynamicParameter = degrees };
this.CurrentImageFormat.ApplyProcessor(hue.ProcessImage, this);
}
return this;
}
/// <summary> /// <summary>
/// Alters the output quality of the current image. /// Alters the output quality of the current image.
/// <remarks> /// <remarks>

1
src/ImageProcessor/ImageProcessor.csproj

@ -121,6 +121,7 @@
<Compile Include="Processors\Brightness.cs" /> <Compile Include="Processors\Brightness.cs" />
<Compile Include="Processors\Contrast.cs" /> <Compile Include="Processors\Contrast.cs" />
<Compile Include="Processors\GaussianSharpen.cs" /> <Compile Include="Processors\GaussianSharpen.cs" />
<Compile Include="Processors\HueRotate.cs" />
<Compile Include="Processors\Hue.cs" /> <Compile Include="Processors\Hue.cs" />
<Compile Include="Processors\Meta.cs" /> <Compile Include="Processors\Meta.cs" />
<Compile Include="Processors\RoundedCorners.cs" /> <Compile Include="Processors\RoundedCorners.cs" />

291
src/ImageProcessor/Imaging/Colors/HSLAColor.cs

@ -12,6 +12,7 @@ namespace ImageProcessor.Imaging.Colors
/// <summary> /// <summary>
/// Represents an HSLA (hue, saturation, luminosity, alpha) color. /// Represents an HSLA (hue, saturation, luminosity, alpha) color.
/// Adapted from <see href="http://richnewman.wordpress.com/about/code-listings-and-diagrams/hslcolor-class/"/>
/// </summary> /// </summary>
public struct HSLAColor public struct HSLAColor
{ {
@ -21,235 +22,293 @@ namespace ImageProcessor.Imaging.Colors
/// <summary> /// <summary>
/// The hue component. /// The hue component.
/// </summary> /// </summary>
private double hue; private double h;
/// <summary> /// <summary>
/// The luminosity component. /// The luminosity component.
/// </summary> /// </summary>
private double luminosity; private double l;
/// <summary> /// <summary>
/// The saturation component. /// The saturation component.
/// </summary> /// </summary>
private double saturation; private double s;
/// <summary> /// <summary>
/// The alpha component. /// The alpha component.
/// </summary> /// </summary>
private double a; private double a;
#region Constructors and Destructors
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="HSLAColor"/> struct. /// Initializes a new instance of the <see cref="HSLAColor"/> struct.
/// </summary> /// </summary>
/// <param name="color"> /// <param name="hue">
/// The color. /// The hue.
/// </param> /// </param>
public HSLAColor(Color color) /// <param name="saturation">
/// The saturation.
/// </param>
/// <param name="luminosity">
/// The luminosity.
/// </param>
public HSLAColor(double hue, double saturation, double luminosity)
: this() : this()
{ {
this.SetRGBA(color.R, color.G, color.B, color.A); this.H = hue;
this.S = saturation;
this.L = luminosity;
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="HSLAColor"/> class. /// Initializes a new instance of the <see cref="HSLAColor"/> struct.
/// </summary> /// </summary>
/// <param name="red"> /// <param name="color">
/// The red. /// The <see cref="System.Drawing.Color"/> to initialize from.
/// </param>
/// <param name="green">
/// The green.
/// </param>
/// <param name="blue">
/// The blue.
/// </param> /// </param>
public HSLAColor(int red, int green, int blue, int alpha) public HSLAColor(Color color)
: this() : this()
{ {
this.SetRGBA(red, green, blue, alpha); HSLAColor hslColor = color;
this.h = hslColor.h;
this.s = hslColor.s;
this.l = hslColor.l;
this.a = hslColor.a;
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="HSLAColor"/> class. /// Gets or sets the hue component.
/// </summary> /// </summary>
/// <param name="hue"> public double H
/// The hue.
/// </param>
/// <param name="saturation">
/// The saturation.
/// </param>
/// <param name="luminosity">
/// The luminosity.
/// </param>
public HSLAColor(double hue, double saturation, double luminosity)
: this()
{ {
this.Hue = hue; get
this.Saturation = saturation; {
this.Luminosity = luminosity; return this.h;
} }
#endregion
#region Public Properties set
{
this.h = this.CheckRange(value);
}
}
/// <summary> /// <summary>
/// Gets or sets the hue. /// Gets or sets the luminosity component.
/// </summary> /// </summary>
public double Hue public double L
{ {
get get
{ {
return this.hue; return this.l;
} }
set set
{ {
this.hue = this.CheckRange(value); this.l = this.CheckRange(value);
} }
} }
/// <summary> /// <summary>
/// Gets or sets the luminosity. /// Gets or sets the saturation component.
/// </summary> /// </summary>
public double Luminosity public double S
{ {
get get
{ {
return this.luminosity; return this.s;
} }
set set
{ {
this.luminosity = this.CheckRange(value); this.s = this.CheckRange(value);
} }
} }
/// <summary> /// <summary>
/// Gets or sets the saturation. /// Gets or sets the alpha component.
/// </summary> /// </summary>
public double Saturation public double A
{ {
get get
{ {
return this.saturation; return this.a;
} }
set set
{ {
this.saturation = this.CheckRange(value); this.a = this.CheckRange(value);
} }
} }
#endregion /// <summary>
/// Allows the implicit conversion of an instance of <see cref="System.Drawing.Color"/> to a
/// <see cref="HSLAColor"/>.
/// </summary>
/// <param name="color">
/// The instance of <see cref="System.Drawing.Color"/> to convert.
/// </param>
/// <returns>
/// An instance of <see cref="HSLAColor"/>.
/// </returns>
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
};
#region Public Methods and Operators return hslColor;
}
/// <summary> /// <summary>
/// The op_ implicit. /// Allows the implicit conversion of an instance of <see cref="System.Drawing.Color"/> to a
/// <see cref="HSLAColor"/>.
/// </summary> /// </summary>
/// <param name="hslColor"> /// <param name="rgbaColor">
/// The hsl color. /// The instance of <see cref="RGBAColor"/> to convert.
/// </param> /// </param>
/// <returns> /// <returns>
/// An instance of <see cref="HSLAColor"/>.
/// </returns> /// </returns>
public static implicit operator Color(HSLAColor hslColor) 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
};
return hslColor;
}
/// <summary>
/// Allows the implicit conversion of an instance of <see cref="HSLAColor"/> to a
/// <see cref="System.Drawing.Color"/>.
/// </summary>
/// <param name="hslaColor">
/// The instance of <see cref="HSLAColor"/> to convert.
/// </param>
/// <returns>
/// An instance of <see cref="System.Drawing.Color"/>.
/// </returns>
public static implicit operator Color(HSLAColor hslaColor)
{ {
double r = 0, g = 0, b = 0; double r = 0, g = 0, b = 0;
if (Math.Abs(hslColor.luminosity - 0) > .0001) if (Math.Abs(hslaColor.l - 0) > .0001)
{ {
if (Math.Abs(hslColor.saturation - 0) <= .0001) if (Math.Abs(hslaColor.s - 0) <= .0001)
{ {
r = g = b = hslColor.luminosity; r = g = b = hslaColor.l;
} }
else else
{ {
double temp2 = GetTemp2(hslColor); double temp2 = GetTemp2(hslaColor);
double temp1 = (2.0 * hslColor.luminosity) - temp2; double temp1 = (2.0 * hslaColor.l) - temp2;
r = GetColorComponent(temp1, temp2, hslColor.hue + (1.0 / 3.0)); r = GetColorComponent(temp1, temp2, hslaColor.h + (1.0 / 3.0));
g = GetColorComponent(temp1, temp2, hslColor.hue); g = GetColorComponent(temp1, temp2, hslaColor.h);
b = GetColorComponent(temp1, temp2, hslColor.hue - (1.0 / 3.0)); b = GetColorComponent(temp1, temp2, hslaColor.h - (1.0 / 3.0));
} }
} }
return Color.FromArgb((int)(255 * r), (int)(255 * g), (int)(255 * b)); return Color.FromArgb(Convert.ToInt32(255 * hslaColor.a), Convert.ToInt32(255 * r), Convert.ToInt32(255 * g), Convert.ToInt32(255 * b));
} }
/// <summary> /// <summary>
/// The op_ implicit. /// Allows the implicit conversion of an instance of <see cref="HSLAColor"/> to a
/// <see cref="RGBAColor"/>.
/// </summary> /// </summary>
/// <param name="color"> /// <param name="hslaColor">
/// The color. /// The instance of <see cref="HSLAColor"/> to convert.
/// </param> /// </param>
/// <returns> /// <returns>
/// An instance of <see cref="RGBAColor"/>.
/// </returns> /// </returns>
public static implicit operator HSLAColor(Color color) public static implicit operator RGBAColor(HSLAColor hslaColor)
{ {
HSLAColor hslColor = new HSLAColor double r = 0, g = 0, b = 0;
if (Math.Abs(hslaColor.l - 0) > .0001)
{ {
hue = color.GetHue() / 360.0, if (Math.Abs(hslaColor.s - 0) <= .0001)
luminosity = color.GetBrightness(), {
saturation = color.GetSaturation() r = g = b = hslaColor.l;
}; }
else
{
double temp2 = GetTemp2(hslaColor);
double temp1 = (2.0 * hslaColor.l) - temp2;
return hslColor; r = GetColorComponent(temp1, temp2, hslaColor.h + (1.0 / 3.0));
g = GetColorComponent(temp1, temp2, hslaColor.h);
b = GetColorComponent(temp1, temp2, hslaColor.h - (1.0 / 3.0));
}
}
return new RGBAColor(Convert.ToByte(255 * r), Convert.ToByte(255 * g), Convert.ToByte(255 * b), Convert.ToByte(255 * hslaColor.a));
} }
/// <summary> /// <summary>
/// The set rgb components. /// Returns a <see cref="System.String" /> that represents this instance.
/// </summary> /// </summary>
/// <param name="red"> /// <returns>
/// The red. /// A <see cref="System.String" /> that represents this instance.
/// </param> /// </returns>
/// <param name="green"> public string ToRGBAString()
/// The green component.
/// </param>
/// <param name="blue">
/// The blue component.
/// </param>
/// <param name="alpha">
/// The alpha component.
/// </param>
public void SetRGBA(int red, int green, int blue, int alpha)
{ {
HSLAColor hslColor = Color.FromArgb(alpha, red, green, blue); Color color = this;
this.hue = hslColor.hue; return string.Format("R={0}, G={1}, B={2}, A={3}", color.R, color.G, color.B, color.A);
this.saturation = hslColor.saturation;
this.luminosity = hslColor.luminosity;
this.a = hslColor.a;
} }
/// <summary> /// <summary>
/// The to rgb string. /// Returns a <see cref="System.String" /> that represents this instance.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// The <see cref="string"/>. /// A <see cref="System.String" /> that represents this instance.
/// </returns> /// </returns>
public string ToRGBString() public override string ToString()
{ {
Color color = this; return string.Format("H={0:#0.##}, S={1:#0.##}, L={2:#0.##}, A={3:#0.##}", this.H, this.S, this.L, this.A);
return string.Format("R: {0:#0.##} G: {1:#0.##} B: {2:#0.##}", color.R, color.G, color.B);
} }
/// <summary> /// <summary>
/// The to string. /// Indicates whether this instance and a specified object are equal.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// The <see cref="string"/>. /// true if <paramref name="obj"/> and this instance are the same type and represent the same value; otherwise, false.
/// </returns> /// </returns>
public override string ToString() /// <param name="obj">Another object to compare to. </param>
public override bool Equals(object obj)
{ {
return string.Format("H: {0:#0.##} S: {1:#0.##} L: {2:#0.##}", this.Hue, this.Saturation, this.Luminosity); if (obj is HSLAColor)
} {
Color thisColor = this;
Color otherColor = (HSLAColor)obj;
return thisColor.Equals(otherColor);
}
#endregion return false;
}
#region Methods /// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>
/// A 32-bit signed integer that is the hash code for this instance.
/// </returns>
public override int GetHashCode()
{
Color thisColor = this;
return thisColor.GetHashCode();
}
/// <summary> /// <summary>
/// The get color component. /// Gets the color component from the given hue values.
/// </summary> /// </summary>
/// <param name="temp1"> /// <param name="temp1">
/// The temp 1. /// The temp 1.
@ -288,7 +347,7 @@ namespace ImageProcessor.Imaging.Colors
/// The get temp 2. /// The get temp 2.
/// </summary> /// </summary>
/// <param name="hslColor"> /// <param name="hslColor">
/// The hsl color. /// The <see cref="HSLAColor"/> color.
/// </param> /// </param>
/// <returns> /// <returns>
/// The <see cref="double"/>. /// The <see cref="double"/>.
@ -296,13 +355,13 @@ namespace ImageProcessor.Imaging.Colors
private static double GetTemp2(HSLAColor hslColor) private static double GetTemp2(HSLAColor hslColor)
{ {
double temp2; double temp2;
if (hslColor.luminosity <= 0.5) if (hslColor.l <= 0.5)
{ {
temp2 = hslColor.luminosity * (1.0 + hslColor.saturation); temp2 = hslColor.l * (1.0 + hslColor.s);
} }
else else
{ {
temp2 = hslColor.luminosity + hslColor.saturation - (hslColor.luminosity * hslColor.saturation); temp2 = hslColor.l + hslColor.s - (hslColor.l * hslColor.s);
} }
return temp2; return temp2;
@ -332,13 +391,13 @@ namespace ImageProcessor.Imaging.Colors
} }
/// <summary> /// <summary>
/// The check range. /// Checks the range of the given value to ensure that it remains within the acceptable boundaries.
/// </summary> /// </summary>
/// <param name="value"> /// <param name="value">
/// The value. /// The value to check.
/// </param> /// </param>
/// <returns> /// <returns>
/// The <see cref="double"/>. /// The sanitized <see cref="double"/>.
/// </returns> /// </returns>
private double CheckRange(double value) private double CheckRange(double value)
{ {
@ -353,7 +412,5 @@ namespace ImageProcessor.Imaging.Colors
return value; return value;
} }
#endregion
} }
} }

91
src/ImageProcessor/Imaging/Colors/RGBAColor.cs

@ -8,6 +8,7 @@
namespace ImageProcessor.Imaging.Colors namespace ImageProcessor.Imaging.Colors
{ {
using System.Drawing; using System.Drawing;
using System.Text;
/// <summary> /// <summary>
/// Represents an RGBA (red, green, blue, alpha) color. /// Represents an RGBA (red, green, blue, alpha) color.
@ -91,6 +92,36 @@ namespace ImageProcessor.Imaging.Colors
this.A = color.A; this.A = color.A;
} }
/// <summary>
/// Allows the implicit conversion of an instance of <see cref="System.Drawing.Color"/> to a
/// <see cref="RGBAColor"/>.
/// </summary>
/// <param name="color">
/// The instance of <see cref="System.Drawing.Color"/> to convert.
/// </param>
/// <returns>
/// An instance of <see cref="RGBAColor"/>.
/// </returns>
public static implicit operator RGBAColor(Color color)
{
return new RGBAColor(color);
}
/// <summary>
/// Allows the implicit conversion of an instance of <see cref="System.Drawing.Color"/> to a
/// <see cref="RGBAColor"/>.
/// </summary>
/// <param name="color">
/// The instance of <see cref="System.Drawing.Color"/> to convert.
/// </param>
/// <returns>
/// An instance of <see cref="RGBAColor"/>.
/// </returns>
public static implicit operator RGBAColor(HSLAColor color)
{
return new RGBAColor(color);
}
/// <summary> /// <summary>
/// Allows the implicit conversion of an instance of <see cref="RGBAColor"/> to a /// Allows the implicit conversion of an instance of <see cref="RGBAColor"/> to a
/// <see cref="System.Drawing.Color"/>. /// <see cref="System.Drawing.Color"/>.
@ -103,7 +134,65 @@ namespace ImageProcessor.Imaging.Colors
/// </returns> /// </returns>
public static implicit operator Color(RGBAColor rgba) public static implicit operator Color(RGBAColor rgba)
{ {
return System.Drawing.Color.FromArgb(rgba.A, rgba.R, rgba.G, rgba.B); return Color.FromArgb(rgba.A, rgba.R, rgba.G, rgba.B);
}
/// <summary>
/// Allows the implicit conversion of an instance of <see cref="RGBAColor"/> to a
/// <see cref="HSLAColor"/>.
/// </summary>
/// <param name="rgba">
/// The instance of <see cref="RGBAColor"/> to convert.
/// </param>
/// <returns>
/// An instance of <see cref="HSLAColor"/>.
/// </returns>
public static implicit operator HSLAColor(RGBAColor rgba)
{
return new HSLAColor(rgba);
}
/// <summary>
/// Returns a <see cref="System.String" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String" /> that represents this instance.
/// </returns>
public override string ToString()
{
return string.Format("R={0}, G={1}, B={2}, A={3}", this.R, this.G, this.B, this.A);
}
/// <summary>
/// Indicates whether this instance and a specified object are equal.
/// </summary>
/// <returns>
/// true if <paramref name="obj"/> and this instance are the same type and represent the same value; otherwise, false.
/// </returns>
/// <param name="obj">Another object to compare to. </param>
public override bool Equals(object obj)
{
if (obj is RGBAColor)
{
Color thisColor = this;
Color otherColor = (RGBAColor)obj;
return thisColor.Equals(otherColor);
}
return false;
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>
/// A 32-bit signed integer that is the hash code for this instance.
/// </returns>
public override int GetHashCode()
{
Color thisColor = this;
return thisColor.GetHashCode();
} }
} }
} }

8
src/ImageProcessor/Processors/Hue.cs

@ -18,7 +18,7 @@ namespace ImageProcessor.Processors
using ImageProcessor.Imaging.Colors; using ImageProcessor.Imaging.Colors;
/// <summary> /// <summary>
/// Encapsulates methods to rotate the hue component of an image. /// Encapsulates methods to adjust the hue component of an image.
/// </summary> /// </summary>
public class Hue : IGraphicsProcessor public class Hue : IGraphicsProcessor
{ {
@ -69,10 +69,8 @@ namespace ImageProcessor.Processors
{ {
for (int j = 0; j < height; j++) for (int j = 0; j < height; j++)
{ {
HSLAColor hsl = new HSLAColor(fastBitmap.GetPixel(i, j)); HSLAColor hsla = new HSLAColor(fastBitmap.GetPixel(i, j)) { H = degrees / 360f };
hsl.Hue = (hsl.Hue + (degrees / 360f)) % 1; fastBitmap.SetPixel(i, j, hsla);
//hsl.Hue = (degrees / 360f);
fastBitmap.SetPixel(i, j, hsl);
} }
} }
} }

95
src/ImageProcessor/Processors/HueRotate.cs

@ -0,0 +1,95 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="HueRotate.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// Encapsulates methods to rotate the hue component of an image.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Processors
{
using System;
using System.Collections.Generic;
using System.Drawing;
using ImageProcessor.Common.Exceptions;
using ImageProcessor.Imaging;
using ImageProcessor.Imaging.Colors;
/// <summary>
/// Encapsulates methods to rotate the hue component of an image.
/// </summary>
public class HueRotate : IGraphicsProcessor
{
/// <summary>
/// Initializes a new instance of the <see cref="HueRotate"/> class.
/// </summary>
public HueRotate()
{
this.Settings = new Dictionary<string, string>();
}
/// <summary>
/// Gets or sets the dynamic parameter.
/// </summary>
public dynamic DynamicParameter { get; set; }
/// <summary>
/// Gets or sets any additional settings required by the processor.
/// </summary>
public Dictionary<string, string> Settings { get; set; }
/// <summary>
/// Processes the image.
/// </summary>
/// <param name="factory">
/// The current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class containing
/// the image to process.
/// </param>
/// <returns>
/// The processed image from the current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class.
/// </returns>
public Image ProcessImage(ImageFactory factory)
{
Bitmap newImage = null;
Image image = factory.Image;
try
{
int degrees = this.DynamicParameter;
int width = image.Width;
int height = image.Height;
newImage = new Bitmap(image);
using (FastBitmap fastBitmap = new FastBitmap(newImage))
{
for (int i = 0; i < width; i++)
{
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);
}
}
}
image.Dispose();
image = newImage;
}
catch (Exception ex)
{
if (newImage != null)
{
newImage.Dispose();
}
throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex);
}
return image;
}
}
}

3
src/ImageProcessorConsole/Program.cs

@ -82,7 +82,8 @@ namespace ImageProcessorConsole
//.Resize(new Size((int)(size.Width * 1.1), 0)) //.Resize(new Size((int)(size.Width * 1.1), 0))
//.ContentAwareResize(layer) //.ContentAwareResize(layer)
.Constrain(size) .Constrain(size)
.Hue(180) .HueRotate(270)
.Quality(100)
.Save(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(path), @"..\..\images\output", fileInfo.Name))); .Save(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(path), @"..\..\images\output", fileInfo.Name)));
stopwatch.Stop(); stopwatch.Stop();

BIN
src/ImageProcessorConsole/images/output/1aaa.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

BIN
src/ImageProcessorConsole/images/output/2006-citybus.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

1
src/ImageProcessorConsole/images/output/2008.jpg.REMOVED.git-id

@ -1 +0,0 @@
73753ca19a0818ee4a88b6e9e0eb85ca17624269

BIN
src/ImageProcessorConsole/images/output/2012-citybus.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

1
src/ImageProcessorConsole/images/output/Arc-de-Triomphe-France.jpg.REMOVED.git-id

@ -1 +0,0 @@
dff097307936637d1c43f82ca28f4582c9810de7

BIN
src/ImageProcessorConsole/images/output/IC580196.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

BIN
src/ImageProcessorConsole/images/output/Turtle.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

BIN
src/ImageProcessorConsole/images/output/arc_de_triomphe_paris_france.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

BIN
src/ImageProcessorConsole/images/output/mountain.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

BIN
src/ImageProcessorConsole/images/output/rotate.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

BIN
src/ImageProcessorConsole/images/output/sample1.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

BIN
src/ImageProcessorConsole/images/output/shutterstock_19173982_Arc_de_triomphe-square1.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

BIN
src/ImageProcessorConsole/images/output/test.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

BIN
src/ImageProcessorConsole/images/output/tower.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Loading…
Cancel
Save