Browse Source

Improving convolution filter speed with Parallel.For

TODO: Check this again and expand to other methods

Former-commit-id: d1e608bee96e75c26c0665518374f4db5af8e899
Former-commit-id: a43b63910def35dc41b4b5a494d00f7c9089e398
pull/17/head
James South 12 years ago
parent
commit
e44e2fd517
  1. 4
      src/ImageProcessor.Playground/Program.cs
  2. 96
      src/ImageProcessor/Imaging/Filters/EdgeDetection/ConvolutionFilter.cs

4
src/ImageProcessor.Playground/Program.cs

@ -77,9 +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())
.DetectEdges(new LaplacianOfGaussianEdgeFilter())
//.EntropyCrop()
.Filter(MatrixFilters.Comic)
//.Filter(MatrixFilters.Comic)
//.Filter(MatrixFilters.Comic)
//.Filter(MatrixFilters.HiSatch)
//.Pixelate(8)

96
src/ImageProcessor/Imaging/Filters/EdgeDetection/ConvolutionFilter.cs

@ -13,6 +13,7 @@ namespace ImageProcessor.Imaging.Filters.EdgeDetection
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Threading.Tasks;
using ImageProcessor.Common.Extensions;
using ImageProcessor.Imaging.Filters.Photo;
@ -92,68 +93,73 @@ 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 gX = 0;
double bX = 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 gX = 0;
double bX = 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)
{
Color currentColor = sourceBitmap.GetPixel(offsetX, offsetY);
double r = currentColor.R;
double g = currentColor.G;
double b = currentColor.B;
break;
}
rX += horizontalFilter[fy, fx] * r;
for (int fx = 0; fx < kernelLength; fx++)
{
int fxr = fx - radius;
int offsetX = x + fxr;
gX += horizontalFilter[fy, fx] * g;
// Skip the column
if (offsetX < 0)
{
continue;
}
bX += horizontalFilter[fy, fx] * b;
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;
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();
// 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);
}
}
Color newColor = Color.FromArgb(red, green, blue);
// ReSharper disable once AccessToDisposedClosure
destinationBitmap.SetPixel(x, y, newColor);
}
});
}
}
}

Loading…
Cancel
Save