diff --git a/src/ImageProcessor.Playground/images/input/circle3.png b/src/ImageProcessor.Playground/images/input/circle3.png
new file mode 100644
index 000000000..f83291fe9
--- /dev/null
+++ b/src/ImageProcessor.Playground/images/input/circle3.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7f6f6f0e7876609f12e7549a4fb605102e62027661a1fe93bbffad96ec5e5731
+size 5322
diff --git a/src/ImageProcessor/Imaging/Convolution.cs b/src/ImageProcessor/Imaging/Convolution.cs
index 8e9495637..36e57df41 100644
--- a/src/ImageProcessor/Imaging/Convolution.cs
+++ b/src/ImageProcessor/Imaging/Convolution.cs
@@ -12,6 +12,7 @@ namespace ImageProcessor.Imaging
{
using System;
using System.Drawing;
+ using System.Threading.Tasks;
using ImageProcessor.Common.Extensions;
@@ -274,101 +275,106 @@ namespace ImageProcessor.Imaging
int threshold = this.Threshold;
// For each line
- for (int y = 0; y < height; y++)
- {
- // For each pixel
- for (int x = 0; x < width; x++)
+ Parallel.For(
+ 0,
+ height,
+ y =>
{
- // 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++)
+ // For each pixel
+ for (int x = 0; x < width; x++)
{
- int ir = i - radius;
- int offsetY = y + ir;
-
- // Skip the current row
- if (offsetY < 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;
- // 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)
+ // Skip the current row
+ if (offsetY < 0)
{
continue;
}
- if (offsetX < width)
+ // Outwith the current bounds so break.
+ if (offsetY >= height)
{
- 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;
+ break;
+ }
- processedKernelSize++;
+ // 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)
+ {
+ // ReSharper disable once AccessToDisposedClosure
+ 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++;
+ }
}
}
- }
- // 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)
+ // Check to see if all kernel elements were processed
+ if (processedKernelSize == kernelSize)
{
- // Apply the set divider.
+ // 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;
+ }
+ }
- // Check and apply the divider
- if ((long)divider != 0)
- {
- red /= divider;
- green /= divider;
- blue /= divider;
- alpha /= divider;
- }
+ // Check and apply the divider
+ if ((long)divider != 0)
+ {
+ red /= divider;
+ green /= divider;
+ blue /= divider;
+ alpha /= divider;
+ }
- // Add any applicable threshold.
- red += threshold;
- green += threshold;
- blue += threshold;
- alpha += threshold;
+ // Add any applicable threshold.
+ red += threshold;
+ green += threshold;
+ blue += threshold;
+ alpha += threshold;
- destinationFastBitmap.SetPixel(x, y, Color.FromArgb(alpha.ToByte(), red.ToByte(), green.ToByte(), blue.ToByte()));
- }
- }
+ // ReSharper disable once AccessToDisposedClosure
+ destinationFastBitmap.SetPixel(x, y, Color.FromArgb(alpha.ToByte(), red.ToByte(), green.ToByte(), blue.ToByte()));
+ }
+ });
}
}
diff --git a/src/ImageProcessor/Imaging/FastBitmap.cs b/src/ImageProcessor/Imaging/FastBitmap.cs
index aea18d326..8b5fd8715 100644
--- a/src/ImageProcessor/Imaging/FastBitmap.cs
+++ b/src/ImageProcessor/Imaging/FastBitmap.cs
@@ -156,6 +156,7 @@ namespace ImageProcessor.Imaging
/// The at the given pixel.
public Color GetPixel(int x, int y)
{
+#if DEBUG
if ((x < 0) || (x >= this.width))
{
throw new ArgumentOutOfRangeException("x", "Value cannot be less than zero or greater than the bitmap width.");
@@ -165,7 +166,7 @@ namespace ImageProcessor.Imaging
{
throw new ArgumentOutOfRangeException("y", "Value cannot be less than zero or greater than the bitmap height.");
}
-
+#endif
PixelData* data = this[x, y];
return Color.FromArgb(data->A, data->R, data->G, data->B);
}
@@ -181,6 +182,7 @@ namespace ImageProcessor.Imaging
///
public void SetPixel(int x, int y, Color color)
{
+#if DEBUG
if ((x < 0) || (x >= this.width))
{
throw new ArgumentOutOfRangeException("x", "Value cannot be less than zero or greater than the bitmap width.");
@@ -190,7 +192,7 @@ namespace ImageProcessor.Imaging
{
throw new ArgumentOutOfRangeException("y", "Value cannot be less than zero or greater than the bitmap height.");
}
-
+#endif
PixelData* data = this[x, y];
data->R = color.R;
data->G = color.G;
diff --git a/src/ImageProcessor/Imaging/Filters/Binarization/BinaryThreshold.cs b/src/ImageProcessor/Imaging/Filters/Binarization/BinaryThreshold.cs
index 96478497f..e8ffa61e7 100644
--- a/src/ImageProcessor/Imaging/Filters/Binarization/BinaryThreshold.cs
+++ b/src/ImageProcessor/Imaging/Filters/Binarization/BinaryThreshold.cs
@@ -11,6 +11,10 @@
namespace ImageProcessor.Imaging.Filters.Binarization
{
using System.Drawing;
+ using System.Drawing.Imaging;
+ using System.Threading.Tasks;
+
+ using ImageProcessor.Imaging.Filters.Photo;
///
/// Performs binary threshold filtering against a given greyscale image.
@@ -20,7 +24,7 @@ namespace ImageProcessor.Imaging.Filters.Binarization
///
/// The threshold value.
///
- private byte threshold = 128;
+ private byte threshold = 10;
///
/// Initializes a new instance of the class.
@@ -61,14 +65,19 @@ namespace ImageProcessor.Imaging.Filters.Binarization
using (FastBitmap sourceBitmap = new FastBitmap(source))
{
- for (int y = 0; y < height; y++)
- {
- for (int x = 0; x < width; x++)
+ Parallel.For(
+ 0,
+ height,
+ y =>
{
- Color color = sourceBitmap.GetPixel(x, y);
- sourceBitmap.SetPixel(x, y, color.B >= this.threshold ? Color.White : Color.Black);
- }
- }
+ for (int x = 0; x < width; x++)
+ {
+ // ReSharper disable AccessToDisposedClosure
+ Color color = sourceBitmap.GetPixel(x, y);
+ sourceBitmap.SetPixel(x, y, color.B >= this.threshold ? Color.White : Color.Black);
+ // ReSharper restore AccessToDisposedClosure
+ }
+ });
}
return source;
diff --git a/src/ImageProcessor/Imaging/Filters/EdgeDetection/ConvolutionFilter.cs b/src/ImageProcessor/Imaging/Filters/EdgeDetection/ConvolutionFilter.cs
index a5ec3c24a..450262c55 100644
--- a/src/ImageProcessor/Imaging/Filters/EdgeDetection/ConvolutionFilter.cs
+++ b/src/ImageProcessor/Imaging/Filters/EdgeDetection/ConvolutionFilter.cs
@@ -49,7 +49,7 @@ namespace ImageProcessor.Imaging.Filters.EdgeDetection
}
///
- /// Processes the given bitmap to apply the current instances .
+ /// Processes the given bitmap to apply the current instance of .
///
/// The image to process.
/// A processed bitmap.
@@ -184,7 +184,7 @@ namespace ImageProcessor.Imaging.Filters.EdgeDetection
}
///
- /// Processes the given bitmap to apply the current instances .
+ /// Processes the given bitmap to apply the current instance of .
///
/// The image to process.
/// A processed bitmap.
@@ -229,74 +229,79 @@ namespace ImageProcessor.Imaging.Filters.EdgeDetection
using (FastBitmap destinationBitmap = new FastBitmap(destination))
{
// Loop through the pixels.
- for (int y = 0; y < height; y++)
- {
- for (int x = 0; x < width; x++)
+ Parallel.For(
+ 0,
+ height,
+ y =>
{
- double rX = 0;
- double rY = 0;
- double gX = 0;
- double gY = 0;
- double bX = 0;
- double bY = 0;
-
- // Apply each matrix multiplier to the color components for each pixel.
- for (int fy = 0; fy < kernelLength; fy++)
+ for (int x = 0; x < width; x++)
{
- 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;
- }
+ double rX = 0;
+ double rY = 0;
+ double gX = 0;
+ double gY = 0;
+ double bX = 0;
+ double bY = 0;
- for (int fx = 0; fx < kernelLength; fx++)
+ // Apply each matrix multiplier to the color components for each pixel.
+ for (int fy = 0; fy < kernelLength; fy++)
{
- int fxr = fx - radius;
- int offsetX = x + fxr;
+ int fyr = fy - radius;
+ int offsetY = y + fyr;
- // Skip the column
- if (offsetX < 0)
+ // Skip the current row
+ if (offsetY < 0)
{
continue;
}
- if (offsetX < width)
+ // Outwith the current bounds so break.
+ if (offsetY >= height)
+ {
+ break;
+ }
+
+ for (int fx = 0; fx < kernelLength; fx++)
{
- Color currentColor = sourceBitmap.GetPixel(offsetX, offsetY);
- double r = currentColor.R;
- double g = currentColor.G;
- double b = currentColor.B;
+ int fxr = fx - radius;
+ int offsetX = x + fxr;
- rX += horizontalFilter[fy, fx] * r;
- rY += verticalFilter[fy, fx] * r;
+ // Skip the column
+ if (offsetX < 0)
+ {
+ continue;
+ }
- gX += horizontalFilter[fy, fx] * g;
- gY += verticalFilter[fy, fx] * g;
+ if (offsetX < width)
+ {
+ // ReSharper disable once AccessToDisposedClosure
+ Color currentColor = sourceBitmap.GetPixel(offsetX, offsetY);
+ double r = currentColor.R;
+ double g = currentColor.G;
+ double b = currentColor.B;
- bX += horizontalFilter[fy, fx] * b;
- bY += verticalFilter[fy, fx] * b;
+ rX += horizontalFilter[fy, fx] * r;
+ rY += verticalFilter[fy, fx] * r;
+
+ gX += horizontalFilter[fy, fx] * g;
+ gY += verticalFilter[fy, fx] * g;
+
+ bX += horizontalFilter[fy, fx] * b;
+ bY += verticalFilter[fy, fx] * b;
+ }
}
}
- }
- // Apply the equation and sanitize.
- byte red = Math.Sqrt((rX * rX) + (rY * rY)).ToByte();
- byte green = Math.Sqrt((gX * gX) + (gY * gY)).ToByte();
- byte blue = Math.Sqrt((bX * bX) + (bY * bY)).ToByte();
+ // Apply the equation and sanitize.
+ byte red = Math.Sqrt((rX * rX) + (rY * rY)).ToByte();
+ byte green = Math.Sqrt((gX * gX) + (gY * gY)).ToByte();
+ byte blue = Math.Sqrt((bX * bX) + (bY * bY)).ToByte();
- Color newColor = Color.FromArgb(red, green, blue);
- destinationBitmap.SetPixel(x, y, newColor);
- }
- }
+ Color newColor = Color.FromArgb(red, green, blue);
+ // ReSharper disable once AccessToDisposedClosure
+ destinationBitmap.SetPixel(x, y, newColor);
+ }
+ });
}
}
}
diff --git a/src/ImageProcessor/Processors/EntropyCrop.cs b/src/ImageProcessor/Processors/EntropyCrop.cs
index f8e6a3199..c14709e48 100644
--- a/src/ImageProcessor/Processors/EntropyCrop.cs
+++ b/src/ImageProcessor/Processors/EntropyCrop.cs
@@ -11,6 +11,7 @@ namespace ImageProcessor.Processors
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
+ using System.IO;
using ImageProcessor.Common.Exceptions;
using ImageProcessor.Imaging;
@@ -59,9 +60,10 @@ namespace ImageProcessor.Processors
try
{
- grey = new ConvolutionFilter(new SobelEdgeFilter(), true).ProcessFilter((Bitmap)image);
+ // Detect the edges then strip out middle shades.
+ grey = new ConvolutionFilter(new SobelEdgeFilter(), true).Process2DFilter((Bitmap)image);
grey = new BinaryThreshold(threshold).ProcessFilter(grey);
-
+
Rectangle rectangle = this.FindBoundingBox(grey, 0);
newImage = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppPArgb);