diff --git a/src/ImageProcessor/ImageFactory.cs b/src/ImageProcessor/ImageFactory.cs
index b27686231a..510803eb54 100644
--- a/src/ImageProcessor/ImageFactory.cs
+++ b/src/ImageProcessor/ImageFactory.cs
@@ -603,37 +603,13 @@ namespace ImageProcessor
/// The angle by which to alter the images hue.
/// Any integer between 0 and 360.
///
- ///
- /// The current instance of the class.
- ///
- public ImageFactory Hue(int degrees)
- {
- // Sanitize the input.
- if (degrees > 360 || degrees < 0)
- {
- degrees = 0;
- }
-
- if (this.ShouldProcess)
- {
- Hue hue = new Hue { DynamicParameter = degrees };
- this.CurrentImageFormat.ApplyProcessor(hue.ProcessImage, this);
- }
-
- return this;
- }
-
- ///
- /// Rotates the hue of the current image altering each color.
- ///
- ///
- /// The angle by which to rotate the images hue.
- /// Any integer between 0 and 360.
+ ///
+ /// Whether to rotate the hue of the current image altering each color
///
///
/// The current instance of the class.
///
- public ImageFactory HueRotate(int degrees)
+ public ImageFactory Hue(int degrees, bool rotate = false)
{
// Sanitize the input.
if (degrees > 360 || degrees < 0)
@@ -641,9 +617,9 @@ namespace ImageProcessor
degrees = 0;
}
- if (this.ShouldProcess)
+ if (this.ShouldProcess && degrees > 0)
{
- HueRotate hue = new HueRotate { DynamicParameter = degrees };
+ Hue hue = new Hue { DynamicParameter = new Tuple(degrees, rotate) };
this.CurrentImageFormat.ApplyProcessor(hue.ProcessImage, this);
}
diff --git a/src/ImageProcessor/ImageProcessor.csproj b/src/ImageProcessor/ImageProcessor.csproj
index a3835a0610..48106d7c4b 100644
--- a/src/ImageProcessor/ImageProcessor.csproj
+++ b/src/ImageProcessor/ImageProcessor.csproj
@@ -122,7 +122,6 @@
-
diff --git a/src/ImageProcessor/Imaging/Convolution.cs b/src/ImageProcessor/Imaging/Convolution.cs
index bc8496ab27..c44d055c02 100644
--- a/src/ImageProcessor/Imaging/Convolution.cs
+++ b/src/ImageProcessor/Imaging/Convolution.cs
@@ -264,145 +264,117 @@ namespace ImageProcessor.Imaging
{
int width = sourceBitmap.Width;
int height = sourceBitmap.Height;
+ Bitmap destinationBitmap = new Bitmap(width, height);
- BitmapData sourceData = sourceBitmap.LockBits(
- new Rectangle(0, 0, width, height),
- ImageLockMode.ReadOnly,
- PixelFormat.Format32bppArgb);
-
- int strideWidth = sourceData.Stride;
- int scanHeight = sourceData.Height;
-
- int bufferSize = strideWidth * scanHeight;
- byte[] pixelBuffer = new byte[bufferSize];
- byte[] resultBuffer = new byte[bufferSize];
-
- Marshal.Copy(sourceData.Scan0, pixelBuffer, 0, pixelBuffer.Length);
- sourceBitmap.UnlockBits(sourceData);
-
- int kernelLength = kernel.GetLength(0);
- int radius = kernelLength >> 1;
- int kernelSize = kernelLength * kernelLength;
-
- // For each line
- for (int y = 0; y < height; y++)
+ using (FastBitmap sourceFastBitmap = new FastBitmap(sourceBitmap))
{
- // For each pixel
- for (int x = 0; x < width; x++)
+ using (FastBitmap destinationFastBitmap = new FastBitmap(destinationBitmap))
{
- // The number of kernel elements taken into account
- int processedKernelSize;
+ int kernelLength = kernel.GetLength(0);
+ int radius = kernelLength >> 1;
+ int kernelSize = kernelLength * kernelLength;
+ int threshold = this.Threshold;
- // Colour sums
- double blue;
- double alpha;
- double divider;
- double green;
- double red = green = blue = alpha = divider = processedKernelSize = 0;
-
- // The location of the pixel bytes.
- int byteOffset = (y * strideWidth) + (x * 4);
-
- // For each kernel row
- for (int i = 0; i < kernelLength; i++)
+ // For each line
+ for (int y = 0; y < height; y++)
{
- int ir = i - radius;
- int offsetY = y + ir;
-
- // Skip the current row
- if (offsetY < 0)
+ // For each pixel
+ for (int x = 0; x < width; x++)
{
- continue;
- }
-
- // Outwith the current bounds so break.
- if (offsetY >= height)
- {
- break;
- }
-
- // For each kernel column
- for (int j = 0; j < kernelLength; j++)
- {
- int jr = j - radius;
- int offsetX = x + jr;
-
- // Skip the column
- if (offsetX < 0)
+ // The number of kernel elements taken into account
+ int processedKernelSize;
+
+ // Colour sums
+ double blue;
+ double alpha;
+ double divider;
+ double green;
+ double red = green = blue = alpha = divider = processedKernelSize = 0;
+
+ // For each kernel row
+ for (int i = 0; i < kernelLength; i++)
{
- continue;
+ int ir = i - radius;
+ int offsetY = y + ir;
+
+ // Skip the current row
+ if (offsetY < 0)
+ {
+ continue;
+ }
+
+ // Outwith the current bounds so break.
+ if (offsetY >= height)
+ {
+ break;
+ }
+
+ // For each kernel column
+ for (int j = 0; j < kernelLength; j++)
+ {
+ int jr = j - radius;
+ int offsetX = x + jr;
+
+ // Skip the column
+ if (offsetX < 0)
+ {
+ continue;
+ }
+
+ if (offsetX < width)
+ {
+ Color color = sourceFastBitmap.GetPixel(offsetX, offsetY);
+ double k = kernel[i, j];
+ divider += k;
+
+ red += k * color.R;
+ green += k * color.G;
+ blue += k * color.B;
+ alpha += k * color.A;
+
+ processedKernelSize++;
+ }
+ }
}
- if (offsetX < width)
+ // Check to see if all kernel elements were processed
+ if (processedKernelSize == kernelSize)
{
- int calcOffset = (offsetX * 4) + (offsetY * sourceData.Stride);
- byte sourceBlue = pixelBuffer[calcOffset];
- byte sourceGreen = pixelBuffer[calcOffset + 1];
- byte sourceRed = pixelBuffer[calcOffset + 2];
- byte sourceAlpha = pixelBuffer[calcOffset + 3];
-
- double k = kernel[i, j];
- divider += k;
-
- red += k * sourceRed;
- green += k * sourceGreen;
- blue += k * sourceBlue;
- alpha += k * sourceAlpha;
+ // All kernel elements are processed; we are not on the edge.
+ divider = this.Divider;
+ }
+ else
+ {
+ // We are on an edge; do we need to use dynamic divider or not?
+ if (!this.UseDynamicDividerForEdges)
+ {
+ // Apply the set divider.
+ divider = this.Divider;
+ }
+ }
- processedKernelSize++;
+ // Check and apply the divider
+ if ((long)divider != 0)
+ {
+ red /= divider;
+ green /= divider;
+ blue /= divider;
+ alpha /= divider;
}
- }
- }
- // Check to see if all kernel elements were processed
- if (processedKernelSize == kernelSize)
- {
- // All kernel elements are processed; we are not on the edge.
- divider = this.Divider;
- }
- else
- {
- // We are on an edge; do we need to use dynamic divider or not?
- if (!this.UseDynamicDividerForEdges)
- {
- // Apply the set divider.
- divider = this.Divider;
- }
- }
+ // Add any applicable threshold.
+ red += threshold;
+ green += threshold;
+ blue += threshold;
+ alpha += threshold;
- // Check and apply the divider
- if ((long)divider != 0)
- {
- red /= divider;
- green /= divider;
- blue /= divider;
- alpha /= divider;
+ destinationFastBitmap.SetPixel(x, y, Color.FromArgb(alpha.ToByte(), red.ToByte(), green.ToByte(), blue.ToByte()));
+ }
}
-
- // Add any applicable threshold.
- red += this.Threshold;
- green += this.Threshold;
- blue += this.Threshold;
- alpha += this.Threshold;
-
- resultBuffer[byteOffset] = blue.ToByte();
- resultBuffer[byteOffset + 1] = green.ToByte();
- resultBuffer[byteOffset + 2] = red.ToByte();
- resultBuffer[byteOffset + 3] = alpha.ToByte();
}
}
- Bitmap resultBitmap = new Bitmap(width, height);
-
- BitmapData resultData = resultBitmap.LockBits(
- new Rectangle(0, 0, width, height),
- ImageLockMode.WriteOnly,
- PixelFormat.Format32bppArgb);
-
- Marshal.Copy(resultBuffer, 0, resultData.Scan0, resultBuffer.Length);
- resultBitmap.UnlockBits(resultData);
-
- return resultBitmap;
+ return destinationBitmap;
}
#region Private
diff --git a/src/ImageProcessor/Processors/Hue.cs b/src/ImageProcessor/Processors/Hue.cs
index 2c59dcc542..4d049c676e 100644
--- a/src/ImageProcessor/Processors/Hue.cs
+++ b/src/ImageProcessor/Processors/Hue.cs
@@ -57,7 +57,10 @@ namespace ImageProcessor.Processors
try
{
- int degrees = this.DynamicParameter;
+
+ Tuple parameters = this.DynamicParameter;
+ int degrees = parameters.Item1;
+ bool rotate = parameters.Item2;
int width = image.Width;
int height = image.Height;
@@ -65,13 +68,28 @@ namespace ImageProcessor.Processors
using (FastBitmap fastBitmap = new FastBitmap(newImage))
{
- for (int i = 0; i < width; i++)
+ if (!rotate)
+ {
+ for (int i = 0; i < width; i++)
+ {
+ for (int j = 0; j < height; j++)
+ {
+ HslaColor original = HslaColor.FromColor(fastBitmap.GetPixel(i, j));
+ HslaColor altered = HslaColor.FromHslaColor(degrees / 360f, original.S, original.L, original.A);
+ fastBitmap.SetPixel(i, j, altered);
+ }
+ }
+ }
+ else
{
- for (int j = 0; j < height; j++)
+ for (int i = 0; i < width; i++)
{
- HslaColor original = HslaColor.FromColor(fastBitmap.GetPixel(i, j));
- HslaColor altered = HslaColor.FromHslaColor(degrees / 360f, original.S, original.L, original.A);
- fastBitmap.SetPixel(i, j, altered);
+ for (int j = 0; j < height; j++)
+ {
+ 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/ImageProcessor/Processors/HueRotate.cs b/src/ImageProcessor/Processors/ReplaceColor.cs
similarity index 52%
rename from src/ImageProcessor/Processors/HueRotate.cs
rename to src/ImageProcessor/Processors/ReplaceColor.cs
index 9d99af892b..37b59b9353 100644
--- a/src/ImageProcessor/Processors/HueRotate.cs
+++ b/src/ImageProcessor/Processors/ReplaceColor.cs
@@ -1,31 +1,21 @@
-// --------------------------------------------------------------------------------------------------------------------
-//
-// Copyright (c) James South.
-// Licensed under the Apache License, Version 2.0.
-//
-//
-// Encapsulates methods to rotate the hue component of an image.
-//
-// --------------------------------------------------------------------------------------------------------------------
-
-namespace ImageProcessor.Processors
+namespace ImageProcessor.Processors
{
using System;
using System.Collections.Generic;
using System.Drawing;
using ImageProcessor.Common.Exceptions;
using ImageProcessor.Imaging;
- using ImageProcessor.Imaging.Colors;
///
- /// Encapsulates methods to rotate the hue component of an image.
+ /// Encapsulates methods allowing the replacement of a color within an image.
+ ///
///
- public class HueRotate : IGraphicsProcessor
+ public class ReplaceColor : IGraphicsProcessor
{
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
- public HueRotate()
+ public ReplaceColor()
{
this.Settings = new Dictionary();
}
@@ -33,12 +23,20 @@ namespace ImageProcessor.Processors
///
/// Gets or sets the dynamic parameter.
///
- public dynamic DynamicParameter { get; set; }
+ public dynamic DynamicParameter
+ {
+ get;
+ set;
+ }
///
/// Gets or sets any additional settings required by the processor.
///
- public Dictionary Settings { get; set; }
+ public Dictionary Settings
+ {
+ get;
+ set;
+ }
///
/// Processes the image.
@@ -57,27 +55,22 @@ namespace ImageProcessor.Processors
try
{
- int degrees = this.DynamicParameter;
- int width = image.Width;
- int height = image.Height;
+ Tuple parameters = this.DynamicParameter;
+ Color original = parameters.Item1;
+ Color replacement = parameters.Item2;
+ int threshold = parameters.Item3;
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 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);
- }
- }
+
+
}
image.Dispose();
image = newImage;
+
}
catch (Exception ex)
{
diff --git a/src/ImageProcessorConsole/Program.cs b/src/ImageProcessorConsole/Program.cs
index 89a510e253..4b7651445c 100644
--- a/src/ImageProcessorConsole/Program.cs
+++ b/src/ImageProcessorConsole/Program.cs
@@ -73,9 +73,10 @@ namespace ImageProcessorConsole
//.BackgroundColor(Color.White)
//.Resize(new Size((int)(size.Width * 1.1), 0))
//.ContentAwareResize(layer)
- //.Constrain(size)
+ .Constrain(size)
//.Filter(MatrixFilters.HiSatch)
- .Pixelate(8)
+ //.Pixelate(8)
+ .GaussianSharpen(10)
.Save(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(path), @"..\..\images\output", fileInfo.Name)));
stopwatch.Stop();