From 64f1d6df24dba6cea1af2854d0ef78a7f4bd190f Mon Sep 17 00:00:00 2001 From: James South Date: Tue, 30 Sep 2014 00:40:02 +0100 Subject: [PATCH] Refactoring + Convolution filter update Former-commit-id: 7f641a754498f9e02fbed2ea8cb2bb923ae84662 --- .../App.config | 0 .../ImageProcessor.Playground.csproj | 0 .../Program.cs | 4 +- .../Properties/AssemblyInfo.cs | 0 .../images/input/120430.gif.REMOVED.git-id | 0 .../images/input/1aaa.jpg.REMOVED.git-id | 0 .../input/2006-citybus.jpg.REMOVED.git-id | 0 .../images/input/2008.jpg.REMOVED.git-id | 0 .../input/2012-citybus.jpg.REMOVED.git-id | 0 .../images/input/4.sm.webp | Bin .../Arc-de-Triomphe-France.jpg.REMOVED.git-id | 0 .../images/input/Bikesgray.png.REMOVED.git-id | 0 .../images/input/IC580196.jpg.REMOVED.git-id | 0 .../images/input/Tl4Yb.gif.REMOVED.git-id | 0 .../images/input/Turtle.jpg | Bin .../Valve_original_(1).PNG.REMOVED.git-id | 0 ...e_triomphe_paris_france.jpg.REMOVED.git-id | 0 .../images/input/circle.png | Bin .../images/input/circle2.png | Bin .../images/input/crop-base-300x200.jpg | Bin 0 -> 14136 bytes .../input/monster-whitebg.png2.REMOVED.git-id | 0 .../images/input/monster.png.REMOVED.git-id | 0 .../images/input/mountain.jpg.REMOVED.git-id | 0 .../images/input/nLpfllv.gif.REMOVED.git-id | 0 .../images/input/new-york.jpg.REMOVED.git-id | 0 .../input/night-bridge.png.REMOVED.git-id | 0 .../images/input/pixel.png3 | Bin .../images/input/rotate.jpg.REMOVED.git-id | 0 .../images/input/sample1.jpg | Bin ...Arc_de_triomphe-square1.jpg.REMOVED.git-id | 0 .../images/input/test.jpg.REMOVED.git-id | 0 .../images/input/test.webp | Bin .../input/tower - Copy.jpg2.REMOVED.git-id | 0 .../images/input/tower.jpg.REMOVED.git-id | 0 src/ImageProcessor.sln | 2 +- src/ImageProcessor/ImageFactory.cs | 11 +- src/ImageProcessor/ImageProcessor.csproj | 9 +- .../Filters/Artistic/OilPaintingFilter.cs | 183 ++++++++++++++++++ .../Filters/Binarization/BinaryThreshold.cs | 5 +- .../EdgeDetection/ConvolutionFilter.cs | 134 ++++++++++++- .../Filters/EdgeDetection/I2DEdgeFilter.cs | 23 +++ .../Filters/EdgeDetection/IEdgeFilter.cs | 5 - .../EdgeDetection/KayyaliEdgeFilter.cs | 2 +- .../Filters/EdgeDetection/KirschEdgeFilter.cs | 2 +- .../EdgeDetection/Laplacian3x3Filter.cs | 36 ++++ .../EdgeDetection/Laplacian5X5Filter.cs | 38 ++++ .../LaplacianOfGaussianFilter.cs | 38 ++++ .../EdgeDetection/PrewittEdgeFilter.cs | 2 +- .../EdgeDetection/RobertsCrossEdgeFilter.cs | 2 +- .../Filters/EdgeDetection/ScharrEdgeFilter.cs | 2 +- .../Filters/EdgeDetection/SobelEdgeFilter.cs | 2 +- .../Filters/Photo/ComicMatrixFilter.cs | 149 +------------- .../Imaging/Formats/FormatUtilities.cs | 1 + .../Imaging/{ => MetaData}/ExifPropertyTag.cs | 2 +- .../{ => MetaData}/ExifPropertyTagType.cs | 2 +- src/ImageProcessor/Processors/AutoRotate.cs | 2 +- src/ImageProcessor/Processors/DetectEdges.cs | 28 +-- src/ImageProcessor/Processors/EntropyCrop.cs | 4 +- src/ImageProcessor/Processors/Hue.cs | 16 +- src/ImageProcessor/Processors/Pixelate.cs | 16 +- src/ImageProcessor/Processors/ReplaceColor.cs | 6 +- src/ImageProcessor/Settings.StyleCop | 1 + src/ImageProcessor_Mono.sln | 2 +- 63 files changed, 531 insertions(+), 198 deletions(-) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/App.config (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/ImageProcessor.Playground.csproj (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/Program.cs (95%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/Properties/AssemblyInfo.cs (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/120430.gif.REMOVED.git-id (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/1aaa.jpg.REMOVED.git-id (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/2006-citybus.jpg.REMOVED.git-id (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/2008.jpg.REMOVED.git-id (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/2012-citybus.jpg.REMOVED.git-id (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/4.sm.webp (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/Arc-de-Triomphe-France.jpg.REMOVED.git-id (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/Bikesgray.png.REMOVED.git-id (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/IC580196.jpg.REMOVED.git-id (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/Tl4Yb.gif.REMOVED.git-id (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/Turtle.jpg (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/Valve_original_(1).PNG.REMOVED.git-id (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/arc_de_triomphe_paris_france.jpg.REMOVED.git-id (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/circle.png (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/circle2.png (100%) create mode 100644 src/ImageProcessor.Playground/images/input/crop-base-300x200.jpg rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/monster-whitebg.png2.REMOVED.git-id (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/monster.png.REMOVED.git-id (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/mountain.jpg.REMOVED.git-id (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/nLpfllv.gif.REMOVED.git-id (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/new-york.jpg.REMOVED.git-id (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/night-bridge.png.REMOVED.git-id (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/pixel.png3 (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/rotate.jpg.REMOVED.git-id (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/sample1.jpg (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/shutterstock_19173982_Arc_de_triomphe-square1.jpg.REMOVED.git-id (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/test.jpg.REMOVED.git-id (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/test.webp (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/tower - Copy.jpg2.REMOVED.git-id (100%) rename src/{ImageProcessorConsole => ImageProcessor.Playground}/images/input/tower.jpg.REMOVED.git-id (100%) create mode 100644 src/ImageProcessor/Imaging/Filters/Artistic/OilPaintingFilter.cs create mode 100644 src/ImageProcessor/Imaging/Filters/EdgeDetection/I2DEdgeFilter.cs create mode 100644 src/ImageProcessor/Imaging/Filters/EdgeDetection/Laplacian3x3Filter.cs create mode 100644 src/ImageProcessor/Imaging/Filters/EdgeDetection/Laplacian5X5Filter.cs create mode 100644 src/ImageProcessor/Imaging/Filters/EdgeDetection/LaplacianOfGaussianFilter.cs rename src/ImageProcessor/Imaging/{ => MetaData}/ExifPropertyTag.cs (99%) rename src/ImageProcessor/Imaging/{ => MetaData}/ExifPropertyTagType.cs (98%) diff --git a/src/ImageProcessorConsole/App.config b/src/ImageProcessor.Playground/App.config similarity index 100% rename from src/ImageProcessorConsole/App.config rename to src/ImageProcessor.Playground/App.config diff --git a/src/ImageProcessorConsole/ImageProcessor.Playground.csproj b/src/ImageProcessor.Playground/ImageProcessor.Playground.csproj similarity index 100% rename from src/ImageProcessorConsole/ImageProcessor.Playground.csproj rename to src/ImageProcessor.Playground/ImageProcessor.Playground.csproj diff --git a/src/ImageProcessorConsole/Program.cs b/src/ImageProcessor.Playground/Program.cs similarity index 95% rename from src/ImageProcessorConsole/Program.cs rename to src/ImageProcessor.Playground/Program.cs index 2d15f83d47..16532da978 100644 --- a/src/ImageProcessorConsole/Program.cs +++ b/src/ImageProcessor.Playground/Program.cs @@ -19,6 +19,7 @@ namespace ImageProcessor.PlayGround using ImageProcessor; using ImageProcessor.Imaging; + using ImageProcessor.Imaging.Filters.EdgeDetection; using ImageProcessor.Imaging.Filters.Photo; /// @@ -76,8 +77,9 @@ namespace ImageProcessor.PlayGround //.ReplaceColor(Color.FromArgb(255, 1, 107, 165), Color.FromArgb(255, 1, 165, 13), 80) //.Resize(layer) //.DetectEdges(new KirschEdgeFilter()) + //.DetectEdges(new LaplacianOfGaussianFilter()) //.EntropyCrop() - .Filter(MatrixFilters.Polaroid) + .Filter(MatrixFilters.Comic) //.Filter(MatrixFilters.Comic) //.Filter(MatrixFilters.HiSatch) //.Pixelate(8) diff --git a/src/ImageProcessorConsole/Properties/AssemblyInfo.cs b/src/ImageProcessor.Playground/Properties/AssemblyInfo.cs similarity index 100% rename from src/ImageProcessorConsole/Properties/AssemblyInfo.cs rename to src/ImageProcessor.Playground/Properties/AssemblyInfo.cs diff --git a/src/ImageProcessorConsole/images/input/120430.gif.REMOVED.git-id b/src/ImageProcessor.Playground/images/input/120430.gif.REMOVED.git-id similarity index 100% rename from src/ImageProcessorConsole/images/input/120430.gif.REMOVED.git-id rename to src/ImageProcessor.Playground/images/input/120430.gif.REMOVED.git-id diff --git a/src/ImageProcessorConsole/images/input/1aaa.jpg.REMOVED.git-id b/src/ImageProcessor.Playground/images/input/1aaa.jpg.REMOVED.git-id similarity index 100% rename from src/ImageProcessorConsole/images/input/1aaa.jpg.REMOVED.git-id rename to src/ImageProcessor.Playground/images/input/1aaa.jpg.REMOVED.git-id diff --git a/src/ImageProcessorConsole/images/input/2006-citybus.jpg.REMOVED.git-id b/src/ImageProcessor.Playground/images/input/2006-citybus.jpg.REMOVED.git-id similarity index 100% rename from src/ImageProcessorConsole/images/input/2006-citybus.jpg.REMOVED.git-id rename to src/ImageProcessor.Playground/images/input/2006-citybus.jpg.REMOVED.git-id diff --git a/src/ImageProcessorConsole/images/input/2008.jpg.REMOVED.git-id b/src/ImageProcessor.Playground/images/input/2008.jpg.REMOVED.git-id similarity index 100% rename from src/ImageProcessorConsole/images/input/2008.jpg.REMOVED.git-id rename to src/ImageProcessor.Playground/images/input/2008.jpg.REMOVED.git-id diff --git a/src/ImageProcessorConsole/images/input/2012-citybus.jpg.REMOVED.git-id b/src/ImageProcessor.Playground/images/input/2012-citybus.jpg.REMOVED.git-id similarity index 100% rename from src/ImageProcessorConsole/images/input/2012-citybus.jpg.REMOVED.git-id rename to src/ImageProcessor.Playground/images/input/2012-citybus.jpg.REMOVED.git-id diff --git a/src/ImageProcessorConsole/images/input/4.sm.webp b/src/ImageProcessor.Playground/images/input/4.sm.webp similarity index 100% rename from src/ImageProcessorConsole/images/input/4.sm.webp rename to src/ImageProcessor.Playground/images/input/4.sm.webp diff --git a/src/ImageProcessorConsole/images/input/Arc-de-Triomphe-France.jpg.REMOVED.git-id b/src/ImageProcessor.Playground/images/input/Arc-de-Triomphe-France.jpg.REMOVED.git-id similarity index 100% rename from src/ImageProcessorConsole/images/input/Arc-de-Triomphe-France.jpg.REMOVED.git-id rename to src/ImageProcessor.Playground/images/input/Arc-de-Triomphe-France.jpg.REMOVED.git-id diff --git a/src/ImageProcessorConsole/images/input/Bikesgray.png.REMOVED.git-id b/src/ImageProcessor.Playground/images/input/Bikesgray.png.REMOVED.git-id similarity index 100% rename from src/ImageProcessorConsole/images/input/Bikesgray.png.REMOVED.git-id rename to src/ImageProcessor.Playground/images/input/Bikesgray.png.REMOVED.git-id diff --git a/src/ImageProcessorConsole/images/input/IC580196.jpg.REMOVED.git-id b/src/ImageProcessor.Playground/images/input/IC580196.jpg.REMOVED.git-id similarity index 100% rename from src/ImageProcessorConsole/images/input/IC580196.jpg.REMOVED.git-id rename to src/ImageProcessor.Playground/images/input/IC580196.jpg.REMOVED.git-id diff --git a/src/ImageProcessorConsole/images/input/Tl4Yb.gif.REMOVED.git-id b/src/ImageProcessor.Playground/images/input/Tl4Yb.gif.REMOVED.git-id similarity index 100% rename from src/ImageProcessorConsole/images/input/Tl4Yb.gif.REMOVED.git-id rename to src/ImageProcessor.Playground/images/input/Tl4Yb.gif.REMOVED.git-id diff --git a/src/ImageProcessorConsole/images/input/Turtle.jpg b/src/ImageProcessor.Playground/images/input/Turtle.jpg similarity index 100% rename from src/ImageProcessorConsole/images/input/Turtle.jpg rename to src/ImageProcessor.Playground/images/input/Turtle.jpg diff --git a/src/ImageProcessorConsole/images/input/Valve_original_(1).PNG.REMOVED.git-id b/src/ImageProcessor.Playground/images/input/Valve_original_(1).PNG.REMOVED.git-id similarity index 100% rename from src/ImageProcessorConsole/images/input/Valve_original_(1).PNG.REMOVED.git-id rename to src/ImageProcessor.Playground/images/input/Valve_original_(1).PNG.REMOVED.git-id diff --git a/src/ImageProcessorConsole/images/input/arc_de_triomphe_paris_france.jpg.REMOVED.git-id b/src/ImageProcessor.Playground/images/input/arc_de_triomphe_paris_france.jpg.REMOVED.git-id similarity index 100% rename from src/ImageProcessorConsole/images/input/arc_de_triomphe_paris_france.jpg.REMOVED.git-id rename to src/ImageProcessor.Playground/images/input/arc_de_triomphe_paris_france.jpg.REMOVED.git-id diff --git a/src/ImageProcessorConsole/images/input/circle.png b/src/ImageProcessor.Playground/images/input/circle.png similarity index 100% rename from src/ImageProcessorConsole/images/input/circle.png rename to src/ImageProcessor.Playground/images/input/circle.png diff --git a/src/ImageProcessorConsole/images/input/circle2.png b/src/ImageProcessor.Playground/images/input/circle2.png similarity index 100% rename from src/ImageProcessorConsole/images/input/circle2.png rename to src/ImageProcessor.Playground/images/input/circle2.png diff --git a/src/ImageProcessor.Playground/images/input/crop-base-300x200.jpg b/src/ImageProcessor.Playground/images/input/crop-base-300x200.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e31a8b05ad8f5d21f46cb8c2b8247ae7ec9d20fd GIT binary patch literal 14136 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 + /// Crops an image to the area of greatest entropy. + ///

+ /// + /// The threshold in bytes to control the entropy. + /// + /// + /// The current instance of the class. + /// public ImageFactory EntropyCrop(byte threshold = 128) { if (this.ShouldProcess) { - EntropyCrop autoCrop = new EntropyCrop() { DynamicParameter = threshold }; + EntropyCrop autoCrop = new EntropyCrop { DynamicParameter = threshold }; this.CurrentImageFormat.ApplyProcessor(autoCrop.ProcessImage, this); } diff --git a/src/ImageProcessor/ImageProcessor.csproj b/src/ImageProcessor/ImageProcessor.csproj index ee7f452678..dd4fa80151 100644 --- a/src/ImageProcessor/ImageProcessor.csproj +++ b/src/ImageProcessor/ImageProcessor.csproj @@ -76,9 +76,14 @@ + + + + + @@ -92,11 +97,11 @@ - + - + diff --git a/src/ImageProcessor/Imaging/Filters/Artistic/OilPaintingFilter.cs b/src/ImageProcessor/Imaging/Filters/Artistic/OilPaintingFilter.cs new file mode 100644 index 0000000000..d659f62038 --- /dev/null +++ b/src/ImageProcessor/Imaging/Filters/Artistic/OilPaintingFilter.cs @@ -0,0 +1,183 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// The oil painting filter. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Imaging.Filters.Artistic +{ + using System; + using System.Drawing; + + using ImageProcessor.Common.Extensions; + + /// + /// The oil painting filter. + /// + public class OilPaintingFilter + { + /// + /// The levels. + /// + private int levels; + + /// + /// The brush size. + /// + private int brushSize; + + /// + /// Initializes a new instance of the class. + /// + /// + /// The number of levels. + /// + /// + /// The brush size. + /// + public OilPaintingFilter(int levels, int brushSize) + { + this.levels = levels; + this.brushSize = brushSize; + } + + /// + /// Gets or sets the number of levels. + /// + public int Levels + { + get + { + return this.levels; + } + + set + { + if (value > 0) + { + this.levels = value; + } + } + } + + /// + /// Gets or sets the brush size. + /// + public int BrushSize + { + get + { + return this.brushSize; + } + + set + { + if (value > 0) + { + this.brushSize = value; + } + } + } + + /// + /// Applies the filter. TODO: Make this class implement an interface? + /// + /// + /// The source. + /// + /// + /// The . + /// + public Bitmap ApplyFilter(Bitmap source) + { + int width = source.Width; + int height = source.Height; + + int radius = this.brushSize >> 1; + + Bitmap destination = new Bitmap(width, height); + using (FastBitmap sourceBitmap = new FastBitmap(source)) + { + using (FastBitmap destinationBitmap = new FastBitmap(destination)) + { + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + int maxIntensity = 0; + int maxIndex = 0; + int[] intensityBin = new int[this.levels]; + int[] blueBin = new int[this.levels]; + int[] greenBin = new int[this.levels]; + int[] redBin = new int[this.levels]; + + for (int i = 0; i <= radius; i++) + { + 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 (int fx = 0; fx <= radius; fx++) + { + int jr = fx - radius; + int offsetX = x + jr; + + // Skip the column + if (offsetX < 0) + { + continue; + } + + if (offsetX < width) + { + Color color = sourceBitmap.GetPixel(offsetX, offsetY); + + byte sourceBlue = color.B; + byte sourceGreen = color.G; + byte sourceRed = color.R; + + int currentIntensity = (int)Math.Round(((sourceBlue + sourceGreen + sourceRed) / 3.0 * (this.levels - 1)) / 255.0); + + intensityBin[currentIntensity] += 1; + blueBin[currentIntensity] += sourceBlue; + greenBin[currentIntensity] += sourceGreen; + redBin[currentIntensity] += sourceRed; + + if (intensityBin[currentIntensity] > maxIntensity) + { + maxIntensity = intensityBin[currentIntensity]; + maxIndex = currentIntensity; + } + } + } + } + + byte blue = Math.Abs(blueBin[maxIndex] / maxIntensity).ToByte(); + byte green = Math.Abs(greenBin[maxIndex] / maxIntensity).ToByte(); + byte red = Math.Abs(redBin[maxIndex] / maxIntensity).ToByte(); + + destinationBitmap.SetPixel(x, y, Color.FromArgb(red, green, blue)); + } + } + } + } + + return destination; + } + } +} diff --git a/src/ImageProcessor/Imaging/Filters/Binarization/BinaryThreshold.cs b/src/ImageProcessor/Imaging/Filters/Binarization/BinaryThreshold.cs index b420a65881..96478497f2 100644 --- a/src/ImageProcessor/Imaging/Filters/Binarization/BinaryThreshold.cs +++ b/src/ImageProcessor/Imaging/Filters/Binarization/BinaryThreshold.cs @@ -61,10 +61,9 @@ namespace ImageProcessor.Imaging.Filters.Binarization using (FastBitmap sourceBitmap = new FastBitmap(source)) { - - for (int x = 0; x < width; x++) + for (int y = 0; y < height; y++) { - for (int y = 0; y < height; y++) + for (int x = 0; x < width; x++) { Color color = sourceBitmap.GetPixel(x, y); sourceBitmap.SetPixel(x, y, color.B >= this.threshold ? Color.White : Color.Black); diff --git a/src/ImageProcessor/Imaging/Filters/EdgeDetection/ConvolutionFilter.cs b/src/ImageProcessor/Imaging/Filters/EdgeDetection/ConvolutionFilter.cs index 9d6681ffcf..98a4e4c0e2 100644 --- a/src/ImageProcessor/Imaging/Filters/EdgeDetection/ConvolutionFilter.cs +++ b/src/ImageProcessor/Imaging/Filters/EdgeDetection/ConvolutionFilter.cs @@ -83,7 +83,137 @@ namespace ImageProcessor.Imaging.Filters.EdgeDetection try { double[,] horizontalFilter = this.edgeFilter.HorizontalGradientOperator; - double[,] verticalFilter = this.edgeFilter.VerticalGradientOperator; + + int kernelLength = horizontalFilter.GetLength(0); + int radius = kernelLength >> 1; + + using (FastBitmap sourceBitmap = new FastBitmap(input)) + { + using (FastBitmap destinationBitmap = new FastBitmap(destination)) + { + // Loop through the pixels. + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + double rX = 0; + double gX = 0; + double bX = 0; + + // Apply each matrix multiplier to the color components for each pixel. + for (int fy = 0; fy < kernelLength; fy++) + { + int fyr = fy - radius; + int offsetY = y + fyr; + + // Skip the current row + if (offsetY < 0) + { + continue; + } + + // Outwith the current bounds so break. + if (offsetY >= height) + { + break; + } + + for (int fx = 0; fx < kernelLength; fx++) + { + int fxr = fx - radius; + int offsetX = x + fxr; + + // Skip the column + if (offsetX < 0) + { + continue; + } + + if (offsetX < width) + { + Color currentColor = sourceBitmap.GetPixel(offsetX, offsetY); + double r = currentColor.R; + double g = currentColor.G; + double b = currentColor.B; + + rX += horizontalFilter[fy, fx] * r; + + gX += horizontalFilter[fy, fx] * g; + + bX += horizontalFilter[fy, fx] * b; + } + } + } + + // Apply the equation and sanitize. + byte red = rX.ToByte(); + byte green = gX.ToByte(); + byte blue = bX.ToByte(); + + Color newColor = Color.FromArgb(red, green, blue); + destinationBitmap.SetPixel(x, y, newColor); + } + } + } + } + } + finally + { + // We created a new image. Cleanup. + input.Dispose(); + } + + // Draw a black rectangle around the area to ensure that the first row/column in covered. + using (Graphics graphics = Graphics.FromImage(destination)) + { + // Draw an edge around the image. + using (Pen blackPen = new Pen(Color.Black)) + { + blackPen.Width = 4; + graphics.DrawRectangle(blackPen, new Rectangle(0, 0, destination.Width, destination.Height)); + } + } + + return destination; + } + + /// + /// Processes the given bitmap to apply the current instances . + /// + /// The image to process. + /// A processed bitmap. + public Bitmap Process2DFilter(Bitmap source) + { + int width = source.Width; + int height = source.Height; + + Bitmap destination = new Bitmap(width, height, PixelFormat.Format32bppArgb); + Bitmap input = new Bitmap(width, height, PixelFormat.Format32bppArgb); + + using (Graphics graphics = Graphics.FromImage(input)) + { + Rectangle rectangle = new Rectangle(0, 0, width, height); + if (this.greyscale) + { + // If it's greyscale apply a colormatrix to the image. + using (ImageAttributes attributes = new ImageAttributes()) + { + attributes.SetColorMatrix(ColorMatrixes.GreyScale); + graphics.DrawImage(source, rectangle, 0, 0, width, height, GraphicsUnit.Pixel, attributes); + } + } + else + { + // Fixes an issue with transparency not converting properly. + graphics.Clear(Color.Transparent); + graphics.DrawImage(source, rectangle); + } + } + + try + { + double[,] horizontalFilter = this.edgeFilter.HorizontalGradientOperator; + double[,] verticalFilter = ((I2DEdgeFilter)this.edgeFilter).VerticalGradientOperator; int kernelLength = horizontalFilter.GetLength(0); int radius = kernelLength >> 1; @@ -176,7 +306,7 @@ namespace ImageProcessor.Imaging.Filters.EdgeDetection // Draw an edge around the image. using (Pen blackPen = new Pen(Color.Black)) { - blackPen.Width = 1; + blackPen.Width = 4; graphics.DrawRectangle(blackPen, new Rectangle(0, 0, destination.Width, destination.Height)); } } diff --git a/src/ImageProcessor/Imaging/Filters/EdgeDetection/I2DEdgeFilter.cs b/src/ImageProcessor/Imaging/Filters/EdgeDetection/I2DEdgeFilter.cs new file mode 100644 index 0000000000..e6568c19f1 --- /dev/null +++ b/src/ImageProcessor/Imaging/Filters/EdgeDetection/I2DEdgeFilter.cs @@ -0,0 +1,23 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Describes properties for creating 2 dimension edge detection filters. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Imaging.Filters.EdgeDetection +{ + /// + /// Describes properties for creating 2 dimension edge detection filters. + /// + public interface I2DEdgeFilter : IEdgeFilter + { + /// + /// Gets the vertical gradient operator. + /// + double[,] VerticalGradientOperator { get; } + } +} diff --git a/src/ImageProcessor/Imaging/Filters/EdgeDetection/IEdgeFilter.cs b/src/ImageProcessor/Imaging/Filters/EdgeDetection/IEdgeFilter.cs index 18a3bc8cc4..b89ce902dc 100644 --- a/src/ImageProcessor/Imaging/Filters/EdgeDetection/IEdgeFilter.cs +++ b/src/ImageProcessor/Imaging/Filters/EdgeDetection/IEdgeFilter.cs @@ -19,10 +19,5 @@ namespace ImageProcessor.Imaging.Filters.EdgeDetection /// Gets the horizontal gradient operator. /// double[,] HorizontalGradientOperator { get; } - - /// - /// Gets the vertical gradient operator. - /// - double[,] VerticalGradientOperator { get; } } } diff --git a/src/ImageProcessor/Imaging/Filters/EdgeDetection/KayyaliEdgeFilter.cs b/src/ImageProcessor/Imaging/Filters/EdgeDetection/KayyaliEdgeFilter.cs index f597b9f5eb..001d405110 100644 --- a/src/ImageProcessor/Imaging/Filters/EdgeDetection/KayyaliEdgeFilter.cs +++ b/src/ImageProcessor/Imaging/Filters/EdgeDetection/KayyaliEdgeFilter.cs @@ -15,7 +15,7 @@ namespace ImageProcessor.Imaging.Filters.EdgeDetection /// The Kayyali operator filter. /// /// - public class KayyaliEdgeFilter : IEdgeFilter + public class KayyaliEdgeFilter : I2DEdgeFilter { /// /// Gets the horizontal gradient operator. diff --git a/src/ImageProcessor/Imaging/Filters/EdgeDetection/KirschEdgeFilter.cs b/src/ImageProcessor/Imaging/Filters/EdgeDetection/KirschEdgeFilter.cs index 9069870d8d..47987078ed 100644 --- a/src/ImageProcessor/Imaging/Filters/EdgeDetection/KirschEdgeFilter.cs +++ b/src/ImageProcessor/Imaging/Filters/EdgeDetection/KirschEdgeFilter.cs @@ -15,7 +15,7 @@ namespace ImageProcessor.Imaging.Filters.EdgeDetection /// The Kirsch operator filter. /// /// - public class KirschEdgeFilter : IEdgeFilter + public class KirschEdgeFilter : I2DEdgeFilter { /// /// Gets the horizontal gradient operator. diff --git a/src/ImageProcessor/Imaging/Filters/EdgeDetection/Laplacian3x3Filter.cs b/src/ImageProcessor/Imaging/Filters/EdgeDetection/Laplacian3x3Filter.cs new file mode 100644 index 0000000000..e4c6944961 --- /dev/null +++ b/src/ImageProcessor/Imaging/Filters/EdgeDetection/Laplacian3x3Filter.cs @@ -0,0 +1,36 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// The Laplacian 3 x 3 operator filter. +// +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Imaging.Filters.EdgeDetection +{ + /// + /// The Laplacian 3 x 3 operator filter. + /// + /// + public class Laplacian3X3Filter : IEdgeFilter + { + /// + /// Gets the horizontal gradient operator. + /// + public double[,] HorizontalGradientOperator + { + get + { + return new double[,] + { + { -1, -1, -1 }, + { -1, 8, -1 }, + { -1, -1, -1 } + }; + } + } + } +} diff --git a/src/ImageProcessor/Imaging/Filters/EdgeDetection/Laplacian5X5Filter.cs b/src/ImageProcessor/Imaging/Filters/EdgeDetection/Laplacian5X5Filter.cs new file mode 100644 index 0000000000..97bd90cf83 --- /dev/null +++ b/src/ImageProcessor/Imaging/Filters/EdgeDetection/Laplacian5X5Filter.cs @@ -0,0 +1,38 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// The Laplacian 5 x 5 operator filter. +// +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Imaging.Filters.EdgeDetection +{ + /// + /// The Laplacian 5 x 5 operator filter. + /// + /// + public class Laplacian5X5Filter : IEdgeFilter + { + /// + /// Gets the horizontal gradient operator. + /// + public double[,] HorizontalGradientOperator + { + get + { + return new double[,] + { + { -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1 }, + { -1, -1, 24, -1, -1 }, + { -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1 } + }; + } + } + } +} diff --git a/src/ImageProcessor/Imaging/Filters/EdgeDetection/LaplacianOfGaussianFilter.cs b/src/ImageProcessor/Imaging/Filters/EdgeDetection/LaplacianOfGaussianFilter.cs new file mode 100644 index 0000000000..b2c4cdd2d1 --- /dev/null +++ b/src/ImageProcessor/Imaging/Filters/EdgeDetection/LaplacianOfGaussianFilter.cs @@ -0,0 +1,38 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// The Laplacian of Gaussian operator filter. +// +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Imaging.Filters.EdgeDetection +{ + /// + /// The Laplacian of Gaussian operator filter. + /// + /// + public class LaplacianOfGaussianFilter : IEdgeFilter + { + /// + /// Gets the horizontal gradient operator. + /// + public double[,] HorizontalGradientOperator + { + get + { + return new double[,] + { + { 0, 0, -1, 0, 0 }, + { 0, -1, -2, -1, 0 }, + { -1, -2, 16, -2, -1 }, + { 0, -1, -2, -1, 0 }, + { 0, 0, -1, 0, 0 } + }; + } + } + } +} diff --git a/src/ImageProcessor/Imaging/Filters/EdgeDetection/PrewittEdgeFilter.cs b/src/ImageProcessor/Imaging/Filters/EdgeDetection/PrewittEdgeFilter.cs index d13f3ae404..91b3272dea 100644 --- a/src/ImageProcessor/Imaging/Filters/EdgeDetection/PrewittEdgeFilter.cs +++ b/src/ImageProcessor/Imaging/Filters/EdgeDetection/PrewittEdgeFilter.cs @@ -15,7 +15,7 @@ namespace ImageProcessor.Imaging.Filters.EdgeDetection /// The Prewitt operator filter. /// /// - public class PrewittEdgeFilter : IEdgeFilter + public class PrewittEdgeFilter : I2DEdgeFilter { /// /// Gets the horizontal gradient operator. diff --git a/src/ImageProcessor/Imaging/Filters/EdgeDetection/RobertsCrossEdgeFilter.cs b/src/ImageProcessor/Imaging/Filters/EdgeDetection/RobertsCrossEdgeFilter.cs index db75c03ab6..b121f9a453 100644 --- a/src/ImageProcessor/Imaging/Filters/EdgeDetection/RobertsCrossEdgeFilter.cs +++ b/src/ImageProcessor/Imaging/Filters/EdgeDetection/RobertsCrossEdgeFilter.cs @@ -15,7 +15,7 @@ namespace ImageProcessor.Imaging.Filters.EdgeDetection /// The Roberts Cross operator filter. /// /// - public class RobertsCrossEdgeFilter : IEdgeFilter + public class RobertsCrossEdgeFilter : I2DEdgeFilter { /// /// Gets the horizontal gradient operator. diff --git a/src/ImageProcessor/Imaging/Filters/EdgeDetection/ScharrEdgeFilter.cs b/src/ImageProcessor/Imaging/Filters/EdgeDetection/ScharrEdgeFilter.cs index 2d5915d368..c346cb0834 100644 --- a/src/ImageProcessor/Imaging/Filters/EdgeDetection/ScharrEdgeFilter.cs +++ b/src/ImageProcessor/Imaging/Filters/EdgeDetection/ScharrEdgeFilter.cs @@ -15,7 +15,7 @@ namespace ImageProcessor.Imaging.Filters.EdgeDetection /// The Scharr operator filter. /// /// - public class ScharrEdgeFilter : IEdgeFilter + public class ScharrEdgeFilter : I2DEdgeFilter { /// /// Gets the horizontal gradient operator. diff --git a/src/ImageProcessor/Imaging/Filters/EdgeDetection/SobelEdgeFilter.cs b/src/ImageProcessor/Imaging/Filters/EdgeDetection/SobelEdgeFilter.cs index bf116164d8..99fd1cf5e8 100644 --- a/src/ImageProcessor/Imaging/Filters/EdgeDetection/SobelEdgeFilter.cs +++ b/src/ImageProcessor/Imaging/Filters/EdgeDetection/SobelEdgeFilter.cs @@ -15,7 +15,7 @@ namespace ImageProcessor.Imaging.Filters.EdgeDetection /// The Sobel operator filter. /// /// - public class SobelEdgeFilter : IEdgeFilter + public class SobelEdgeFilter : I2DEdgeFilter { /// /// Gets the horizontal gradient operator. diff --git a/src/ImageProcessor/Imaging/Filters/Photo/ComicMatrixFilter.cs b/src/ImageProcessor/Imaging/Filters/Photo/ComicMatrixFilter.cs index 6c63b49cb1..0f5bcad66f 100644 --- a/src/ImageProcessor/Imaging/Filters/Photo/ComicMatrixFilter.cs +++ b/src/ImageProcessor/Imaging/Filters/Photo/ComicMatrixFilter.cs @@ -10,7 +10,6 @@ namespace ImageProcessor.Imaging.Filters.Photo { - #region Using using System; using System.Drawing; using System.Drawing.Drawing2D; @@ -18,8 +17,7 @@ namespace ImageProcessor.Imaging.Filters.Photo using System.Runtime.InteropServices; using ImageProcessor.Common.Extensions; - - #endregion + using ImageProcessor.Imaging.Filters.Artistic; /// /// Encapsulates methods with which to add a comic filter to an image. @@ -62,8 +60,8 @@ namespace ImageProcessor.Imaging.Filters.Photo highBitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppPArgb); // Apply a oil painting filter to the image. - highBitmap = OilPaintFilter((Bitmap)image, 3, 5); - + highBitmap = new OilPaintingFilter(3, 5).ApplyFilter((Bitmap)image); + // Draw the edges. edgeBitmap = DrawEdges((Bitmap)image, 120); @@ -109,7 +107,7 @@ namespace ImageProcessor.Imaging.Filters.Photo using (Graphics graphics = Graphics.FromImage(newImage)) { - // graphics.Clear(Color.Transparent); + graphics.Clear(Color.Transparent); // Overlay the image. graphics.DrawImage(highBitmap, 0, 0); @@ -166,135 +164,6 @@ namespace ImageProcessor.Imaging.Filters.Photo return image; } - /// - /// Applies an oil paint filter. - /// TODO: Move this to another class and add to the factory - /// - /// - /// The source bitmap. - /// - /// - /// The levels. - /// - /// - /// The filter size. - /// - /// - /// The . - /// - private static Bitmap OilPaintFilter(Bitmap sourceBitmap, int levels, int filterSize) - { - int width = sourceBitmap.Width; - int height = sourceBitmap.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); - - levels = levels - 1; - - int radius = filterSize >> 1; - - for (int y = 0; y < height; y++) - { - for (int x = 0; x < width; x++) - { - int maxIntensity = 0; - int maxIndex = 0; - int[] intensityBin = new int[levels + 1]; - int[] blueBin = new int[levels + 1]; - int[] greenBin = new int[levels + 1]; - int[] redBin = new int[levels + 1]; - - int byteOffset = (y * strideWidth) + (x * 4); - - for (int i = 0; i <= radius; i++) - { - 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 (int j = 0; j <= radius; j++) - { - int jr = j - radius; - int offsetX = x + jr; - - // Skip the column - if (offsetX < 0) - { - continue; - } - - if (offsetX < width) - { - int calcOffset = (offsetX * 4) + (offsetY * sourceData.Stride); - - byte sourceBlue = pixelBuffer[calcOffset]; - byte sourceGreen = pixelBuffer[calcOffset + 1]; - byte sourceRed = pixelBuffer[calcOffset + 2]; - - int currentIntensity = (int)Math.Round(((sourceBlue + sourceGreen + sourceRed) / 3.0 * levels) / 255.0); - - intensityBin[currentIntensity] += 1; - blueBin[currentIntensity] += sourceBlue; - greenBin[currentIntensity] += sourceGreen; - redBin[currentIntensity] += sourceRed; - - if (intensityBin[currentIntensity] > maxIntensity) - { - maxIntensity = intensityBin[currentIntensity]; - maxIndex = currentIntensity; - } - } - } - } - - double blue = Math.Abs(blueBin[maxIndex] / maxIntensity); - double green = Math.Abs(greenBin[maxIndex] / maxIntensity); - double red = Math.Abs(redBin[maxIndex] / maxIntensity); - - resultBuffer[byteOffset] = blue.ToByte(); - resultBuffer[byteOffset + 1] = green.ToByte(); - resultBuffer[byteOffset + 2] = red.ToByte(); - resultBuffer[byteOffset + 3] = pixelBuffer[byteOffset + 3]; - } - } - - 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; - } - /// /// Detects and draws edges. /// TODO: Move this to another class and do edge detection. @@ -514,16 +383,16 @@ namespace ImageProcessor.Imaging.Filters.Photo int width = source.Width; int height = source.Height; - for (int i = 0; i < width; i++) + for (int y = 0; y < height; y++) { - for (int j = 0; j < height; j++) + for (int x = 0; x < width; x++) { - Color sourceColor = sourceBitmap.GetPixel(i, j); - Color destinationColor = destinationBitmap.GetPixel(i, j); + Color sourceColor = sourceBitmap.GetPixel(x, y); + Color destinationColor = destinationBitmap.GetPixel(x, y); if (destinationColor.A != 0) { - destinationBitmap.SetPixel(i, j, Color.FromArgb(sourceColor.B, destinationColor.R, destinationColor.G, destinationColor.B)); + destinationBitmap.SetPixel(x, y, Color.FromArgb(sourceColor.B, destinationColor.R, destinationColor.G, destinationColor.B)); } } } diff --git a/src/ImageProcessor/Imaging/Formats/FormatUtilities.cs b/src/ImageProcessor/Imaging/Formats/FormatUtilities.cs index 53025bf425..49378385db 100644 --- a/src/ImageProcessor/Imaging/Formats/FormatUtilities.cs +++ b/src/ImageProcessor/Imaging/Formats/FormatUtilities.cs @@ -19,6 +19,7 @@ namespace ImageProcessor.Imaging.Formats using System.Reflection; using ImageProcessor.Configuration; + using ImageProcessor.Imaging.MetaData; /// /// Utility methods for working with supported image formats. diff --git a/src/ImageProcessor/Imaging/ExifPropertyTag.cs b/src/ImageProcessor/Imaging/MetaData/ExifPropertyTag.cs similarity index 99% rename from src/ImageProcessor/Imaging/ExifPropertyTag.cs rename to src/ImageProcessor/Imaging/MetaData/ExifPropertyTag.cs index d3c26ff533..29bdd17456 100644 --- a/src/ImageProcessor/Imaging/ExifPropertyTag.cs +++ b/src/ImageProcessor/Imaging/MetaData/ExifPropertyTag.cs @@ -8,7 +8,7 @@ // // -------------------------------------------------------------------------------------------------------------------- -namespace ImageProcessor.Imaging +namespace ImageProcessor.Imaging.MetaData { /// /// The following enum gives descriptions of the property items supported by Windows GDI+. diff --git a/src/ImageProcessor/Imaging/ExifPropertyTagType.cs b/src/ImageProcessor/Imaging/MetaData/ExifPropertyTagType.cs similarity index 98% rename from src/ImageProcessor/Imaging/ExifPropertyTagType.cs rename to src/ImageProcessor/Imaging/MetaData/ExifPropertyTagType.cs index 1d0d470f70..02fa213627 100644 --- a/src/ImageProcessor/Imaging/ExifPropertyTagType.cs +++ b/src/ImageProcessor/Imaging/MetaData/ExifPropertyTagType.cs @@ -9,7 +9,7 @@ // // -------------------------------------------------------------------------------------------------------------------- -namespace ImageProcessor.Imaging +namespace ImageProcessor.Imaging.MetaData { /// /// Specifies the data type of the values stored in the value data member of that same PropertyItem object. diff --git a/src/ImageProcessor/Processors/AutoRotate.cs b/src/ImageProcessor/Processors/AutoRotate.cs index 7368d25744..67b91f81dc 100644 --- a/src/ImageProcessor/Processors/AutoRotate.cs +++ b/src/ImageProcessor/Processors/AutoRotate.cs @@ -16,7 +16,7 @@ namespace ImageProcessor.Processors using System.Drawing; using ImageProcessor.Common.Exceptions; - using ImageProcessor.Imaging; + using ImageProcessor.Imaging.MetaData; /// /// Performs auto-rotation to ensure that EXIF defined rotation is reflected in diff --git a/src/ImageProcessor/Processors/DetectEdges.cs b/src/ImageProcessor/Processors/DetectEdges.cs index db5c278366..1f0d480e8d 100644 --- a/src/ImageProcessor/Processors/DetectEdges.cs +++ b/src/ImageProcessor/Processors/DetectEdges.cs @@ -66,23 +66,27 @@ namespace ImageProcessor.Processors IEdgeFilter filter = parameters.Item1; bool greyscale = parameters.Item2; - //try - //{ + try + { ConvolutionFilter convolutionFilter = new ConvolutionFilter(filter, greyscale); - newImage = convolutionFilter.ProcessFilter((Bitmap)image); + + // Check and assign the correct method. Don't use reflection for speed. + newImage = filter is I2DEdgeFilter + ? convolutionFilter.Process2DFilter((Bitmap)image) + : convolutionFilter.ProcessFilter((Bitmap)image); image.Dispose(); image = newImage; - //} - //catch (Exception ex) - //{ - // if (newImage != null) - // { - // newImage.Dispose(); - // } + } + catch (Exception ex) + { + if (newImage != null) + { + newImage.Dispose(); + } - // throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); - //} + throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); + } return image; } diff --git a/src/ImageProcessor/Processors/EntropyCrop.cs b/src/ImageProcessor/Processors/EntropyCrop.cs index e92ccb64e7..f8e6a31991 100644 --- a/src/ImageProcessor/Processors/EntropyCrop.cs +++ b/src/ImageProcessor/Processors/EntropyCrop.cs @@ -18,7 +18,7 @@ namespace ImageProcessor.Processors using ImageProcessor.Imaging.Filters.EdgeDetection; /// - /// The auto crop. + /// Performs a crop on an image to the area of greatest entropy. /// public class EntropyCrop : IGraphicsProcessor { @@ -194,7 +194,7 @@ namespace ImageProcessor.Processors stopX = getMaxX(fastBitmap); } - return new Rectangle(startX, startY, stopX - startX + 1, stopY - startY + 1); + return new Rectangle(startX + 1, startY + 1, stopX - (startX + 1), stopY - (startY + 1)); } } } \ No newline at end of file diff --git a/src/ImageProcessor/Processors/Hue.cs b/src/ImageProcessor/Processors/Hue.cs index 11a7b48410..a3ccc4c5ef 100644 --- a/src/ImageProcessor/Processors/Hue.cs +++ b/src/ImageProcessor/Processors/Hue.cs @@ -69,25 +69,25 @@ namespace ImageProcessor.Processors { if (!rotate) { - for (int i = 0; i < width; i++) + for (int y = 0; y < height; y++) { - for (int j = 0; j < height; j++) + for (int x = 0; x < width; x++) { - HslaColor original = HslaColor.FromColor(fastBitmap.GetPixel(i, j)); + HslaColor original = HslaColor.FromColor(fastBitmap.GetPixel(x, y)); HslaColor altered = HslaColor.FromHslaColor(degrees / 360f, original.S, original.L, original.A); - fastBitmap.SetPixel(i, j, altered); + fastBitmap.SetPixel(x, y, altered); } } } else { - for (int i = 0; i < width; i++) + for (int y = 0; y < height; y++) { - for (int j = 0; j < height; j++) + for (int x = 0; x < width; x++) { - HslaColor original = HslaColor.FromColor(fastBitmap.GetPixel(i, j)); + HslaColor original = HslaColor.FromColor(fastBitmap.GetPixel(x, y)); HslaColor altered = HslaColor.FromHslaColor((original.H + (degrees / 360f)) % 1, original.S, original.L, original.A); - fastBitmap.SetPixel(i, j, altered); + fastBitmap.SetPixel(x, y, altered); } } } diff --git a/src/ImageProcessor/Processors/Pixelate.cs b/src/ImageProcessor/Processors/Pixelate.cs index ebec47f43b..437388eb0a 100644 --- a/src/ImageProcessor/Processors/Pixelate.cs +++ b/src/ImageProcessor/Processors/Pixelate.cs @@ -82,31 +82,31 @@ namespace ImageProcessor.Processors using (FastBitmap fastBitmap = new FastBitmap(newImage)) { - for (int i = x; i < x + width && i < maxWidth; i += size) + for (int j = y; j < y + height && j < maxHeight; j += size) { - for (int j = y; j < y + height && j < maxHeight; j += size) + for (int i = x; i < x + width && i < maxWidth; i += size) { int offsetX = offset; int offsetY = offset; // Make sure that the offset is within the boundary of the image. - while (i + offsetX >= maxWidth) + while (j + offsetY >= maxHeight) { - offsetX--; + offsetY--; } - while (j + offsetY >= maxHeight) + while (i + offsetX >= maxWidth) { - offsetY--; + offsetX--; } // Get the pixel color in the centre of the soon to be pixelated area. Color pixel = fastBitmap.GetPixel(i + offsetX, j + offsetY); // For each pixel in the pixelate size, set it to the centre color. - for (int k = i; k < i + size && k < maxWidth; k++) + for (int l = j; l < j + size && l < maxHeight; l++) { - for (int l = j; l < j + size && l < maxHeight; l++) + for (int k = i; k < i + size && k < maxWidth; k++) { fastBitmap.SetPixel(k, l, pixel); } diff --git a/src/ImageProcessor/Processors/ReplaceColor.cs b/src/ImageProcessor/Processors/ReplaceColor.cs index 9e3df1eeb9..81266be1e9 100644 --- a/src/ImageProcessor/Processors/ReplaceColor.cs +++ b/src/ImageProcessor/Processors/ReplaceColor.cs @@ -85,9 +85,9 @@ namespace ImageProcessor.Processors using (FastBitmap fastBitmap = new FastBitmap(newImage)) { - for (int x = 0; x < width; x++) + for (int y = 0; y < height; y++) { - for (int y = 0; y < height; y++) + for (int x = 0; x < width; x++) { // Get the pixel color. Color currentColor = fastBitmap.GetPixel(x, y); @@ -103,7 +103,7 @@ namespace ImageProcessor.Processors { if (currentB <= originalB + fuzziness && currentB >= originalB - fuzziness) { - // Ensure the values are withing an acceptable byte range + // Ensure the values are within an acceptable byte range // and set the new value. byte r = (originalR - currentR + replacementR).ToByte(); byte g = (originalG - currentG + replacementG).ToByte(); diff --git a/src/ImageProcessor/Settings.StyleCop b/src/ImageProcessor/Settings.StyleCop index 0a9f862fa5..b3c2af4287 100644 --- a/src/ImageProcessor/Settings.StyleCop +++ b/src/ImageProcessor/Settings.StyleCop @@ -7,6 +7,7 @@ dllimport gps Kayyali + Laplacian mmmm orig Scharr diff --git a/src/ImageProcessor_Mono.sln b/src/ImageProcessor_Mono.sln index 8b1e0fb375..85c0255608 100644 --- a/src/ImageProcessor_Mono.sln +++ b/src/ImageProcessor_Mono.sln @@ -16,7 +16,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessor.Web_NET4", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessor.Web_NET45", "ImageProcessor.Web\NET45\ImageProcessor.Web_NET45.csproj", "{D011A778-59C8-4BFA-A770-C350216BF161}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessorConsole", "ImageProcessorConsole\ImageProcessorConsole.csproj", "{7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessor.Playground", "ImageProcessor.Playground\ImageProcessor.Playground.csproj", "{7BF5274B-56A7-4B62-8105-E9BDF25BAFE7}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessor.UnitTests", "ImageProcessor.UnitTests\ImageProcessor.UnitTests.csproj", "{03CA9055-F997-428C-BF28-F50F991777C6}" EndProject